home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-01-11 | 66.4 KB | 3,670 lines |
- */beginfile FLP2_asm
-
- ; --------------------------------------------------------------
- ; FLP2_asm - FLP Physical I/O - Amiga specific disk access
- ; - last modified 11/01/98
-
- ; Amiga-QDOS sources by Rainer Kowallik
- ; ...latest changes by Mark J Swift
- ; --------------------------------------------------------------
-
- ; Version message
-
- BANNER:
- dc.b 0,34,'Amiga-QDOS FLP physical I/O v1.30',$A
-
- ; -------------------------------------------------------------
- ; Set up Basic procedures
-
- user_ini:
- movem.l d1-d3/a0-a5,-(a7)
-
- lea BANNER(pc),a1 ; start of message
- suba.l a0,a0 ; output channel 0
- move.w UT.MTEXT,a2
- jsr (a2) ; print it
-
- ; link in additional BASIC commands
-
- lea PROC_DEF(pc),a1
- suba.l a2,a2
- move.w $110,a2
- jsr (a2)
-
- ; allocate memory for disk variables
-
- move.l #FV_LEN,d1
- moveq #MT.ALCHP,d0
- moveq #0,d2
- trap #1
- move.l a0,AV.DSKV
-
- ; allow disk DMA.
-
- move.w #%1000000000010000,DMACON ; enable disk DMA
-
- ; clear all the variables
-
- move.l AV.DSKV,a3 ; address of disk vars ->a3
- moveq #((FV_LEN>>1)-1),d0
-
- CLRV_LUP1:
- clr.w (a3)+
- dbra d0,CLRV_LUP1
-
- ; set up disk flags for:
- ; Disable disk operation via index interrupt.
- ; Write operation. Index on write. No index on read
- ; WORDSYNC on. No retry on read error.
-
- move.l AV.DSKV,a3 ; address of disk vars ->a3
- move.w #%0110100000100000,FV.FLAGS(a3)
-
- ; link in polled routine to control switching off the motor
-
- lea POLSERV(pc),a1 ; address of routine
- move.l AV.DSKV,a0
- lea FV.POLLLink(a0),a0
- move.l a1,4(a0)
- moveq #MT.LPOLL,d0
- trap #1
-
- ; check availability of external drive(s)
-
- move.l AV.DSKV,a3 ; address of disk vars ->a3
- lea FV.DRVVArs(a3),a4 ; address of drive vars->a4
-
- moveq #2,d3 ; 3 drives to check
-
- AVAIL_LUP:
- moveq #3,d0
- sub.w d3,d0
- bsr hw_DRV_TYP
- beq.s NODRV
-
- lea DV_LEN(a4),a4
- move.l d0,DV.TYPE(a4)
-
- dbra d3,AVAIL_LUP
-
- NODRV addq.w #1,d3
- moveq #3,d0
- sub.w d3,d0
- move.w d0,FV.MAXDRive(a3)
-
- ; mount each and every drive
-
- move.w d0,d3
-
- MOUNT_LUP:
- move.w d3,d0
- bsr.s MOUNT ; mount drive
-
- dbra d3,MOUNT_LUP ; continue with next drive
-
- INI_RTS:
- movem.l (a7)+,d1-d3/a0-a5
- moveq #0,d0
- rts
-
- ; -------------------------------------------------------------
- ; initialise and set the individual drive variables
-
- MOUNT:
- movem.l d3/a3-a5,-(a7)
-
- move.w d0,d3 ; drive number to d3
-
- move.l AV.DSKV,a3 ; address of disk vars ->a3
- lea FV.DRVVArs(a3),a4 ; address of drive vars->a4
-
- mulu.w #DV_LEN,d3
- lea 0(a4,d3.w),a4 ; relevant drive vars
-
- move.w d0,d3 ; drive number to d3
-
- ; initialise and set the individual drive variables
-
- clr.w DV.TIMEOut(a4) ; timeout
- clr.w DV.SIDE(a4) ; side
- clr.w DV.TRACK(a4) ; track
-
- ; allocate some room for drives buffer variables
-
- ALOCBUF:
- move.l DV.SIDE0buff(a4),d0
- bne.s MOUNTOK ; already defined
-
- movem.l d1-d3/a1-a4,-(a7)
- move.l #(2*AB.BUFENd),d1
- moveq #MT.ALCHP,d0
- moveq #0,d2
- trap #1
- movem.l (a7)+,d1-d3/a1-a4
-
- tst.l d0
- bne.s MOUNTX ; exit on error
-
- move.l a0,a5
-
- move.l a5,DV.SIDE0buff(a4) ; addrs buffer vars, side 0
- move.w d3,AB.DRIVE(a5) ; set disk #
- clr.w AB.SIDE(a5) ; set first side
- clr.w AB.TRACK(a5) ; set first track
- clr.w AB.PENDWflag(a5) ; clear pending write
- move.w #511,AB.BADFLag(a5) ; sectors all bad
-
- lea AB.BUFENd(a5),a5
-
- move.l a5,DV.SIDE1buff(a4) ; addrs buffer vars, side 1
- move.w d3,AB.DRIVE(a5) ; set disk #
- move.w #1,AB.SIDE(a5) ; set second side
- clr.w AB.TRACK(a5) ; set first track
- clr.w AB.PENDWflag(a5) ; clear pending write
- move.w #511,AB.BADFLag(a5) ; sectors all bad
-
- ; initialise drive status
-
- move.w d3,d0
-
- bset d0,FV.CNGFLag(a3) ; set disk changed
- bclr d0,FV.RDYFLag(a3) ; set drive not ready
-
- bsr hw_GO_TK0
-
- MOUNTOK:
- moveq #0,d0
-
- cmp.w FV.MAXDRive(a3),d3
- ble.s MOUNTX
- move.w d3,FV.MAXDRive(a3)
-
- MOUNTX:
- movem.l (a7)+,d3/a3-a5
-
- rts
-
- ; -------------------------------------------------------------
- ; interfacing to the CST floppy controller body
-
- fd_read:
- movem.l d0/d3-d4/a3,-(a7)
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'RD',d0
- bsr IOD0
- move.l #0,a0
- move.l d1,d0
- bsr HEX08
- movem.l (a7)+,d0/a0
- endc
-
- moveq #0,d3
- move.w fdd_rbeg(a3),d3 ; get no of bytes to skip
- moveq #0,d4
- move.w fdd_rend(a3),d4 ; get no of bytes to leave
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- fd_readl:
- bsr RQSEC
-
- move.w d0,d2 ; error return in d2 !
- movem.l (a7)+,d0/d3-d4/a3
- rts
-
- ; -------------------------------------------------------------
- fd_ftrack:
- movem.l a3,-(a7)
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'FT',d0
- bsr IOD0
- movem.l (a7)+,d0/a0
- endc
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- fd_ftrackl:
- bsr FTRACK
-
- movem.l (a7)+,a3
- rts
-
- ; -------------------------------------------------------------
- fd_write:
- movem.l d0/a3,-(a7)
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'WR',d0
- bsr IOD0
- move.l #0,a0
- move.l d1,d0
- bsr HEX08
- movem.l (a7)+,d0/a0
- endc
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- fd_writel:
- bsr WQSEC
-
- move.w d0,d2 ; error return in d2 !
- movem.l (a7)+,d0/a3
- rts
-
- ; -------------------------------------------------------------
- fd_side:
- movem.l d0-d1/a3,-(a7)
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'SD',d0
- bsr IOD0
- move.l #0,a0
- move.l d1,d0
- bsr HEX08
- movem.l (a7)+,d0/a0
- endc
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- fd_sidel:
- moveq #0,d0
- move.b d1,d0
- bsr SEL_SIDE
-
- movem.l (a7)+,d0-d1/a3
- rts
-
- ; -------------------------------------------------------------
- fd_select:
- movem.l d0-d1/a3,-(a7)
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'SL',d0
- bsr IOD0
- move.l #0,a0
- move.l d1,d0
- bsr HEX08
- movem.l (a7)+,d0/a0
- endc
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- fd_selctl:
- cmp.b #4,d1 ; drive within range ?
- bgt.s fd_slctx
-
- moveq #0,d0
- move.b d1,d0
- subq.b #1,d0
- ext.w d0
- bsr SEL_DRV
-
- fd_slctx
- movem.l (a7)+,d0-d1/a3
- rts
-
- ; -------------------------------------------------------------
- fd_seek:
- movem.l d0-d1/a3,-(a7)
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'SK',d0
- bsr IOD0
- move.l #0,a0
- move.l d1,d0
- bsr HEX08
- movem.l (a7)+,d0/a0
- endc
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- fd_seekl:
- moveq #0,d0
- move.b d1,d0
- bsr GO_TRACK
-
- movem.l (a7)+,d0-d1/a3
- rts
-
- ; -------------------------------------------------------------
- fd_restore:
- movem.l a3,-(a7)
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'RS',d0
- bsr IOD0
- movem.l (a7)+,d0/a0
- endc
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- fd_restrl:
- moveq #0,d0
- bsr GO_TRACK
-
- movem.l (a7)+,a3
- rts
-
- ; -------------------------------------------------------------
- fd_wpro:
- movem.l a3,-(a7)
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'WP',d0
- bsr IOD0
- movem.l (a7)+,d0/a0
- endc
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- fd_wprol:
- bsr WPRO
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- bsr HEX08
- movem.l (a7)+,d0/a0
- endc
-
- movem.l (a7)+,a3
- rts
-
- ; -------------------------------------------------------------
- fd_chng:
- movem.l a3,-(a7)
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'CG',d0
- bsr IOD0
- movem.l (a7)+,d0/a0
- endc
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- fd_chngl:
- bsr CHNG
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- bsr HEX08
- movem.l (a7)+,d0/a0
- endc
-
- movem.l (a7)+,a3
- rts
-
- ; -------------------------------------------------------------
- fd_ckrdy:
- movem.l a3,-(a7)
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'CK',d0
- bsr IOD0
- movem.l (a7)+,d0/a0
- endc
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- fd_ckrdyl:
- bsr CKRDY
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- bsr HEX08
- movem.l (a7)+,d0/a0
- endc
-
- movem.l (a7)+,a3
- rts
-
- ; -------------------------------------------------------------
- fd_raddr:
- movem.l d2/a0/a3-a5,-(a7)
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'RA',d0
- bsr IOD0
- movem.l (a7)+,d0/a0
- endc
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- fd_raddrl:
- move.w FV.REQDRive(a3),d0 ; Required drive in d0
- and.w #$3,d0 ; Only drives 0-3.
-
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- move.w DV.TRACK(a4),d1
-
- movem.l (a7)+,d2/a0/a3-a5
- moveq #0,d0
- rts
-
- ; -------------------------------------------------------------
- fd_dskcng:
- movem.l d0/a3,-(a7)
-
- ifd debug
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'CD',d0
- bsr IOD0
- movem.l (a7)+,d0/a0
- endc
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- fd_dscngl:
- move.w FV.REQDRive(a3),d0
-
- bsr DSKCNG
-
- movem.l (a7)+,d0/a3
- rts
-
- ; -------------------------------------------------------------
- ; Flush ASCII buffer for drive d0.w, only if it is truely
- ; owned by that drive. Called before motor is switched off
- ; Error returned in d0.
- ; -------------------------------------------------------------
- FLUSH_BUFF:
- movem.l d1-d2,-(a7)
-
- move.w FV.REQDRive(a3),d2 ; save old required drive
- move.w d0,FV.REQDRive(a3) ; select this drive
- bsr WQDISK ; write the buffer out
- move.w d2,FV.REQDRive(a3) ; restore old drive
-
- FLUSH_BUFX:
- tst.b d0
- movem.l (a7)+,d1-d2
- rts
-
- ; -------------------------------------------------------------
- ; Free ASCII buffer for drive d0.w by flushing contents,
- ; irrespective of the owner. Called before new data is
- ; loaded into the buffer. Error returned in d0.
- ; -------------------------------------------------------------
- FREE_BUFF:
- movem.l d2/a3-a5,-(a7)
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- and.w #$3,d0 ; Only drives 0-3.
-
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- move.w DV.SIDE(a4),d2 ; Address of buffer vars
- lsl.w #2,d2 ; for required side in a5
- move.l DV.SIDE0buff(a4,d2.w),a5
-
- moveq #0,d0
- tst.w AB.PENDWflag(a5) ; any pending writes ?
- beq.s FREE_BUFX ; no !
-
- move.w FV.REQDRive(a3),d2 ; save old required drive
- move.w AB.DRIVE(a5),FV.REQDRive(a3)
- bsr WQDISK ; write the buffer out
- move.w d2,FV.REQDRive(a3) ; restore old drive
-
- FREE_BUFX:
- tst.b d0
- movem.l (a7)+,d2/a3-a5
- rts
-
- ; -------------------------------------------------------------
- ; Format current track for drive FV.REQDRive then verify track.
- ; Error returned in d0.
- ; -------------------------------------------------------------
- FTRACK:
- movem.l d2/a3-a5,-(a7)
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- move.w FV.REQDRive(a3),d0
- and.w #$3,d0 ; only drives 0-3
-
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- move.w DV.SIDE(a4),d2 ; Address of buffer vars
- lsl.w #2,d2 ; for required side in a5
- move.l DV.SIDE0buff(a4,d2.w),a5
-
- move.w #511,AB.PENDWflag(a5); indicate a write pending
- move.w #511,AB.BADFLag(a5) ; and all sectors bad
- move.w d0,AB.DRIVE(a5)
- move.w d0,d2 ; save drive number
- bsr WQDISK ; write track to disk
-
- clr.w AB.BADFLag(a5)
- bset d2,FV.CNGFLag(a3) ; signal disk change so as
- bclr d2,FV.RDYFLag(a3) ; to force a track read
-
- FTRACKX:
- tst.l d0
-
- movem.l (a7)+,d2/a3-a5
- rts
-
- ; -------------------------------------------------------------
- ; Write one Track:
- ; If the writeflag is not set, then skip this operation
- ; Now prepare this Track and code it to MFM, write it to Disk,
- ; and reset the writeflag. Error returned in d0.
- ; -------------------------------------------------------------
- WQDISK:
- movem.l d1-d2/d4-d5/a0-a1/a3-a5,-(a7)
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- move.w FV.REQDRive(a3),d0
- and.w #$3,d0 ; only drives 0-3
-
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- move.w DV.SIDE(a4),d2 ; Address of buffer vars
- lsl.w #2,d2 ; for required side in a5
- move.l DV.SIDE0buff(a4,d2.w),a5
-
- tst.w AB.PENDWflag(a5) ; any pending writes ?
- beq WQABORT_OK ; no !
-
- cmp.w AB.DRIVE(a5),d0 ; does buffer belong to me?
- bne WQABORT_OK ; no !
-
- ; check write protect status before trying to write
-
- bsr WPRO
- tst.b d0
- bne WQABORT_WP
-
- ; make sure drive is switched on
- move.w FV.REQDRive(a3),d0
- bsr SEL_DRV ; check and switch on drive
- bne WQABORT_NF ; drive not found
-
- WQDSK1:
- move.l #MFMBUFFER,a1 ; address of MFM buffer, a1
-
- clr.w FV.LASTBit(a3) ; new MFM calculation
-
- ; Now write 9 sectors in QDOS format
-
- moveq #0,d4 ; initialise sector count
-
- ; make some room between index mark and first header
-
- moveq #91,d1 ; counter for 92 words
- WQROOMLP:
- moveq #$4E,d0 ; byte to write is $4E
- bsr ASCMFMD0
- move.w d0,(a1)+
- dbra d1,WQROOMLP
-
- WQDSKLP:
-
- ; preamble
-
- moveq #83,d1 ; counter for 24+60 words
- WQPRELP:
- moveq #$4E,d0 ; byte to write is $4E
- bsr ASCMFMD0
- move.w d0,(a1)+
- dbra d1,WQPRELP
-
- ; syncron 1
-
- moveq #11,d1 ; counter for 12 words
- WQSYNLP1:
- moveq #0,d0 ; byte to write is 0
- bsr ASCMFMD0
- move.w d0,(a1)+
- dbra d1,WQSYNLP1
-
- ; header block
-
- move.l #$44894489,(a1)+ ; write 3 MFM sync words
- move.l #$44895554,(a1)+ ; and header block ID
-
- move.w #$A1FE,FV.LASTBit(a3) ; set last bit variable
-
- ; create an ASCII header block for this sector
-
- lea 6(a1),a0 ; a reasonably safe place
-
- move.w DV.TRACK(a4),d0
- move.b d0,(a0)+ ; track 0-79
- move.w DV.SIDE(a4),d0
- move.b d0,(a0)+ ; side 0/1
- move.b d4,(a0)
- addq.b #1,(a0)+ ; sector 1-9
- move.b #2,(a0)+ ; bytes/sector, 2=512
-
- lea -4(a0),a0 ; start of ASCII header
- moveq #4,d1 ; bytes in CRC calculation
- move.w #$B230,d0 ; initialise CRC
- bsr CALCCRC
- move.w d0,4(a0) ; write ASCII CRC
-
- moveq #$5,d1 ; count for 6 ASCII bytes
-
- WQHEDLP:
- move.b (a0)+,d0
- bsr ASCMFMD0
- move.w d0,(a1)+
- dbra d1,WQHEDLP
-
- ; trailer 1
-
- moveq #21,d1 ; count for 22 MFM words
-
- WQTRLLP1:
- moveq #$4E,d0 ; byte to write is $4E
- bsr ASCMFMD0
- move.w d0,(a1)+
- dbra d1,WQTRLLP1
-
- ; syncron 2
-
- moveq #11,d1 ; count for 12 MFM words
-
- WQSYNLP2:
- moveq #0,d0 ; byte to write is 0
- bsr ASCMFMD0
- move.w d0,(a1)+
- dbra d1,WQSYNLP2
-
- ; data block
-
- move.l #$44894489,(a1)+ ; write 3 MFM sync words
- move.l #$44895545,(a1)+ ; and data block ID
-
- move.w #$A1FB,FV.LASTBit(a3) ; set last bit variable
-
- move.w AB.BADFLag(a5),d0
- btst d4,d0 ; check if sector is OK
- beq.s WQDSK2
-
- ; sector is bad or undefined so create one from scratch
-
- move.l #$252AA52A,(a1)+ ; initialise with 512 MFM
- move.w #254,d1 ; words. The MFM equivalent
- ; of $30.
- WQINILP:
- move.l #$A52AA52A,(a1)+
- dbra d1,WQINILP
-
- move.l #$44952551,(a1)+ ; write MFM of CRC word
-
- move.w #$A73D,FV.LASTBit(a3) ; set last bit variable
-
- bra WQDSK3
-
- ; sector is OK so use proper ASCII buffer
-
- WQDSK2:
- move.l d4,d0 ; sector number-1
- lsl.w #2,d0 ; find offset
- move.l AB.SCTR1(a5,d0.w),a0 ; ASCII buffer address
-
- move.w #513,d1 ; 514 ASCII bytes
-
- WQDATLP:
- move.b (a0)+,d0
- bsr ASCMFMD0
- move.w d0,(a1)+
- dbra d1,WQDATLP
-
- WQDSK3:
- addq #1,d4
- cmpi.b #8,d4
- ble WQDSKLP
-
- ; write excess bytes
-
- move.w #(WLEN/2-(92+9*(24+60+12+10+22+12+518))),d1
-
- WQXESLP:
- moveq #$4E,d0 ; byte to write is $4E
- bsr ASCMFMD0
- move.w d0,(a1)+
- dbra d1,WQXESLP
-
- ; now write MFM track
-
- move.w AB.DRIVE(a5),d0
- move.w DV.SIDE(a4),d1
- move.w DV.TRACK(a4),d2
- move.l #MFMBUFFER,a0 ; start of track image
-
- ifd debug
-
- movem.l d0/a0,-(a7) ; temporary aberration
- suba.l a0,a0
- move.w AB.DRIVE(a5),d0
- bsr HEX08
- move.w DV.SIDE(a4),d0
- bsr HEX08
- move.w DV.TRACK(a4),d0
- bsr HEX08
- movem.l (a7)+,d0/a0
-
- movem.l d0/a0,-(a7) ; temporary aberration
- suba.l a0,a0
- move.l #$00020000+'of',d0
- bsr IOD0
- movem.l (a7)+,d0/a0
-
- endc
-
- bsr SCR_OFF
-
- ifd debug
-
- movem.l d0/a0,-(a7) ; temporary aberration
- suba.l a0,a0
- move.l #$00020000+'=o',d0
- bsr IOD0
- movem.l (a7)+,d0/a0
-
- endc
-
- bsr hw_WR_DSK ; write buffer to disk
-
- ; make flags right
-
- clr.w AB.PENDWflag(a5)
-
- bclr d0,FV.CNGFLag(a3)
-
- ; invalidate mfm buffer
-
- move.l #MFMBUFFER,a1 ; address of MFM buffer, a1
- lea 184(a1),a1
- moveq #8,d0 ; loop 9 times
-
- WQSCRUB:
- lea 198(a1),a1
- clr.w (a1)
- lea 88(a1),a1
- clr.w (a1)
- lea 1030(a1),a1
- dbra d0,WQSCRUB
-
- WQABORT_OK:
- moveq #0,d0
- bra.s WQDISKX
-
- WQABORT_WP:
- moveq #-20,d0 ; signal writeprotect
- bra.s WQDISKX
-
- WQABORT_NF:
- moveq #-7,d0 ; signal drive not found
-
- WQDISKX:
- tst.b d0
- movem.l (a7)+,d1-d2/d4-d5/a0-a1/a3-a5
- rts
-
- ; -------------------------------------------------------------
- ; The following section uses a slightly different conventions
- ; in order to adopt it to the CST floppy controller software.
- ; The sector is passed in D1, the I/O buffer address in A1
- ; -------------------------------------------------------------
-
- ; -------------------------------------------------------------
- ; Read one Track:
- ; If the Track in the Buffer has the Writeflag set, then write
- ; this track !
- ; Now read a track, and decode it according to MFM conventions
- ; -------------------------------------------------------------
- RQDISK:
- movem.l d1-d3/a0-a5,-(a7)
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- move.w FV.REQDRive(a3),d0
- and.w #$3,d0 ; only drives 0-3
-
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- move.w DV.SIDE(a4),d2 ; Address of buffer vars
- lsl.w #2,d2 ; for required side in a5
- move.l DV.SIDE0buff(a4,d2.w),a5
-
- ; first check if buffer already contains correct info
-
- cmp.w AB.DRIVE(a5),d0
- bne.s RQDISK1
-
- move.w DV.SIDE(a4),d1
- cmp.w AB.SIDE(a5),d1
- bne.s RQDISK1
-
- move.w DV.TRACK(a4),d1
- cmp.w AB.TRACK(a5),d1
- bne.s RQDISK1
-
- ; disk changed?
-
- bsr CHNG
- tst.b d0
- beq RQABORT_OK ; quit if disk not changed
-
- ; now check for pending write operations
-
- RQDISK1:
-
- bsr FREE_BUFF
- bne RQDISKX ; cannot free buffer
-
- ; make sure drive is switched on
-
- move.w FV.REQDRive(a3),d0
- bsr SEL_DRV ; check and switch on drive
- bne RQABORT_NF ; drive not found
-
- ; indicate new owner of this buffer
-
- move.w FV.REQDRive(a3),AB.DRIVE(a5)
- move.w DV.SIDE(a4),AB.SIDE(a5)
- move.w DV.TRACK(a4),AB.TRACK(a5)
-
- ; currently no changes to sectors
-
- clr.w AB.PENDWflag(a5)
-
- ; currently no good sectors at all
-
- move.w #511,AB.BADFLag(a5)
-
- move.w FV.FLAGS(a3),d3
- and.w #%0000000000100000,d3 ; number of retries
- lsr.w #3,d3
-
- RQTRYLOOP:
- lea AB.BUFBEg(a5),a0 ; address to put ASCII
- movem.l a0,-(a7) ; save for later
-
-
- ; now read MFM track
-
- move.w AB.DRIVE(a5),d0
- move.w DV.SIDE(a4),d1
- move.w DV.TRACK(a4),d2
- move.l #MFMBUFFER,a0 ; start of track image
-
- ifd debug
-
- movem.l d0/a0,-(a7) ; temporary aberration
- suba.l a0,a0
- move.w AB.DRIVE(a5),d0
- bsr HEX08
- move.w DV.SIDE(a4),d0
- bsr HEX08
- move.w DV.TRACK(a4),d0
- bsr HEX08
- movem.l (a7)+,d0/a0
-
- movem.l d0/a0,-(a7) ; temporary aberration
- suba.l a0,a0
- move.l #$00020000+'of',d0
- bsr IOD0
- movem.l (a7)+,d0/a0
-
- endc
-
- bsr SCR_OFF
-
- ifd debug
-
- movem.l d0/a0,-(a7) ; temporary aberration
- suba.l a0,a0
- move.l #$00020000+'=i',d0
- bsr IOD0
- movem.l (a7)+,d0/a0
-
- endc
-
- bsr hw_RD_DSK
-
- movem.l (a7)+,a0 ; ASCII buffer -> a0
-
- bne RQRETRY
-
- ; signal disk has not changed
-
- bclr d0,FV.CNGFLag(a3)
-
- ; begin MFM translation
-
- move.l #MFMBUFFER,a1 ; track image -> a1
- lea $4000(a1),a2 ; end of track image
-
- ; first search for header block in track image
-
- RQDSKLP2:
- cmpi.w #$4489,(a1)+ ; find sync pattern
- beq.s RQDSK1
- cmpa.l a2,a1
- blt.s RQDSKLP2
- bra RQRETRY
-
- RQDSK1:
- cmpi.w #$4489,(a1) ; skip over sync
- bne.s RQDSK2
- addq.l #2,a1
- bra.s RQDSK1
-
- RQDSK2:
- cmp.w #$5554,(a1) ; find header block marker
- bne RQDSKLP2
-
- ; header block found OK
-
- clr.w (a1)+ ; make sure its not re-used
- moveq #0,d1 ; counter for 6 ASCII bytes
-
- RQDSKLP3:
- move.w (a1)+,d0
- cmp.w #$4489,d0 ; drop out if sync found
- beq RQDSK1
- bsr MFMASCD0
- move.b d0,0(a0,d1.w) ; store header as ASCII
- addq.w #1,d1
- cmp.w #6,d1
- blt.s RQDSKLP3
-
- moveq #4,d1
- move.w #$B230,d0 ; initialise CRC
- bsr CALCCRC ; calculate CRC for header
-
- move.w 4(a0),d1 ; get CRC read from disk
- cmp.w d0,d1 ; compare with calculated
- beq RQDSK3 ; continue if OK
-
- ifd debug
-
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'-h',d0
- bsr IOD0
- move.l #0,a0
- move.l #$00020000+'??',d0
- bsr IOD0
- movem.l (a7)+,d0/a0
-
- endc
-
- lea -12(a1),a1 ; otherwise search for
- bra RQDSKLP2 ; another header sync
-
- RQDSK3:
- move.w AB.DRIVE(a5),d0
- moveq #0,d2
- move.b (a0),d2 ; check track
- sub.w DV.TRACK(a4),d2
- beq.s RQDSK3A
-
- bgt.s RQDSKL2
-
- RQDSKL1:
- bsr hw_STEP_IN ; increase track
- addq.w #1,d2
- blt.s RQDSKL1
-
- bra RQRETRY
-
- RQDSKL2:
- bsr hw_STEP_OUT ; decrease track
- subq.w #1,d2
- bgt.s RQDSKL2
-
- bra RQRETRY
-
- RQDSK3A:
- move.w DV.SIDE(a4),d1
- cmp.b 1(a0),d1 ; check side
- beq.s RQDSK3B
-
- bsr hw_SEL_SIDE
- bra RQRETRY
-
- RQDSK3B:
- moveq #0,d2
- move.b 2(a0),d2 ; get sector number
- subq #1,d2
-
- ifd debug
-
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'+h',d0
- bsr IOD0
- move.l #0,a0
- move.l d2,d0
- bsr HEX08
- movem.l (a7)+,d0/a0
-
- endc
-
- move.w AB.BADFLag(a5),d0
- btst d2,d0
- beq RQDSKLP2
-
- ; CRC for header block was OK, now search for data block
-
- RQDSK4:
- cmpi.w #$4489,(a1)+ ; find sync pattern
- beq.s RQDSK5
- cmpa.l a2,a1
- blt.s RQDSK4
- bra RQRETRY
-
- RQDSK5:
- cmpi.w #$4489,(a1) ; skip over sync
- bne.s RQDSK6
- addq.l #2,a1
- bra.s RQDSK5
-
- RQDSK6:
- cmp.w #$5545,(a1) ; find data block marker
- bne RQDSK2 ; data block was not found
-
- ; data block found OK
-
- RQDSK7:
- clr.w (a1)+ ; make sure its not re-used
- moveq #0,d1 ; counter for 514 bytes
-
- RQDSKLP4:
- move.w (a1)+,d0
- cmp.w #$4489,d0 ; drop out if sync found
- beq RQDSK1
- bsr MFMASCD0
- move.b d0,0(a0,d1.w)
- addq.w #1,d1
- cmp.w #$202,d1
- blt.s RQDSKLP4
-
- move.w #$200,d1
- move.w #$E295,d0 ; initialise CRC
- bsr CALCCRC ; calculate CRC for data
-
- move.w $200(a0),d1 ; get CRC read from disk
- cmp.w d0,d1 ; compare with calculated
- beq RQDSK8 ; and continue if OK
-
- ifd debug
-
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'-d',d0
- bsr IOD0
- move.l #0,a0
- move.l d2,d0
- bsr HEX08
- movem.l (a7)+,d0/a0
-
- endc
-
- lea -$404(a1),a1 ; otherwise search for
- bra RQDSKLP2 ; another header sync
-
- ; CRC for data block was OK
-
- RQDSK8:
- ifd debug
-
- movem.l d0/a0,-(a7) ; temporary aberration
- move.l #0,a0
- move.l #$00020000+'+d',d0
- bsr IOD0
- move.l #0,a0
- move.l d2,d0
- bsr HEX08
- movem.l (a7)+,d0/a0
-
- endc
-
- move.w d2,d0
- lsl.w #2,d0
- move.l a0,AB.SCTR1(a5,d0.w) ; store data address
-
- lea $202(a0),a0 ; skip over data, 512 bytes
-
- move.w AB.BADFLag(a5),d0
- bclr d2,d0
- move.w d0,AB.BADFLag(a5)
-
- bne RQDSKLP2
-
- RQABORT_OK:
- moveq #0,d0
- bra.s RQDISKX
-
- RQRETRY:
- dbra d3,RQTRYLOOP
-
- RQABORT_BM:
- moveq #ERR.FE,d0 ; bad or changed medium
- bra.s RQDISKX
-
- RQABORT_NF:
- moveq #ERR.NF,d0 ; signal drive not found
-
- RQDISKX:
- tst.b d0
- movem.l (a7)+,d1-d3/a0-a5
- rts
-
- ; -------------------------------------------------------------
- ; Write one sector (D1) from buffer (A1)
- ; If the actual parameters are not the same as for the track in
- ; the track buffer, then call RQDISK.
- ; Copy (A1) to Track buffer
- ; set writeflag !
- ; -------------------------------------------------------------
- WQSEC:
- movem.l d1-d2/a0-a5,-(a7)
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- move.w FV.REQDRive(a3),d0
- and.w #$3,d0 ; only drives 0-3
-
- cmp.w FV.MAXDRive(a3),d0
- bgt.s WQSEC_BM
-
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- move.w DV.SIDE(a4),d2 ; Address of buffer vars
- lsl.w #2,d2 ; for required side in a5
- move.l DV.SIDE0buff(a4,d2.w),a5
-
- ; first check if buffers contain correct info
-
- cmp.w AB.DRIVE(a5),d0
- bne.s WQSEC1
-
- move.w DV.SIDE(a4),d2
- cmp.w AB.SIDE(a5),d2
- bne.s WQSEC1
-
- move.w DV.TRACK(a4),d2
- cmp.w AB.TRACK(a5),d2
- bne.s WQSEC1
-
- ; disk changed?
-
- bsr CHNG
- tst.b d0
- beq.s WQSEC2
-
- ; if so, read correct track into buffers
-
- WQSEC1 move.w FV.REQDRive(a3),d0
- bsr RQDISK
- bne WQSECX
-
- ; determine position of sector
-
- WQSEC2:
- moveq #0,d0
- move.b d1,d0
- lsl.w #2,d0
- move.l AB.SCTR1(a5,d0.w),a0 ; address of ASCII data
-
- move.w #511,d0 ; load counter
-
- WQSEC3:
- move.b (a1)+,(a0)+ ; copy 512 bytes
- dbra d0,WQSEC3
-
- lea -512(a0),a0 ; start of ASCII data
- move.w #512,d1 ; count of bytes
- move.w #$E295,d0 ; initialise CRC
- bsr CALCCRC
- move.w d0,512(a0) ; write ASCII CRC for data
-
- bset.w d1,AB.PENDWflag(a5) ; mark sector for write
- bclr.w d1,AB.BADFLag(a5) ; mark sector as OK
-
- moveq #0,d0
-
- move.w #200,DV.TIMEOut(a4)
-
- bra WQSECX
-
- WQSEC_BM:
- moveq #-16,d0 ; bad or changed medium
-
- WQSECX:
- tst.b d0
- movem.l (a7)+,d1-d2/a0-a5
- rts
-
- ; -------------------------------------------------------------
- ; Read one Sector (D1) to buffer (A1) , (A1 points to the end)
- ; skip (D3) bytes, and leave (D4) at the end
- ;
- ; call RQDISK and copy sector from Track buffer to (A1)
- ; -------------------------------------------------------------
- RQSEC:
- movem.l d1-d2/a0/a2-a5,-(a7)
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- move.w FV.REQDRive(a3),d0
- and.w #$3,d0 ; only drives 0-3
-
- cmp.w FV.MAXDRive(a3),d0
- bgt RQSEC_BM
-
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- move.w DV.SIDE(a4),d2 ; Address of buffer vars
- lsl.w #2,d2 ; for required side in a5
- move.l DV.SIDE0buff(a4,d2.w),a5
-
- ; first check if buffer already contains correct info
-
- cmp.w AB.DRIVE(a5),d0
- bne.s RQSEC1
-
- move.w DV.SIDE(a4),d2
- cmp.w AB.SIDE(a5),d2
- bne.s RQSEC1
-
- move.w DV.TRACK(a4),d2
- cmp.w AB.TRACK(a5),d2
- bne.s RQSEC1
-
- ; disk changed?
-
- bsr CHNG
- tst.b d0
- bne.s RQSEC1 ; read again if changed
-
- ; sector data bad?
-
- move.w AB.BADFLag(a5),d2
- btst d1,d2
- beq.s RQSEC2 ; sector data OK
-
- RQSEC1:
-
- bsr RQDISK
-
- move.w AB.BADFLag(a5),d2
- btst d1,d2
- bne RQSEC_BM
-
- ; determine position of sector
-
- RQSEC2:
- moveq #0,d0
- move.b d1,d0
- lsl.w #2,d0
- move.l AB.SCTR1(a5,d0.w),a0 ; address of ASCII
-
- and.l #$1FF,d3 ; maximum bytes to skip
- add.l d3,a0 ; subtract bytes to skip
- move.w #511,d0 ; load counter
- sub.w d3,d0 ; subtract bytes to skip
- sub.w d4,d0 ; subtract bytes to leave
-
- RQSEC3 move.b (a0)+,(a1)+ ; copy 512 bytes
- dbra d0,RQSEC3
-
- RQSEC_OK:
- moveq #0,d0
- bra.s RQSECX
-
- RQSEC_BM:
- moveq #-16,d0 ; bad or changed medium
-
- RQSECX:
- tst.b d0
- movem.l (a7)+,d1-d2/a0/a2-a5
- rts
-
- ; -------------------------------------------------------------
- ; calculate the Cyclic Redundancy Check for d1 bytes at (a0)
- ; Initial CRC is passed in d0, modified CRC is returned in d0
- ; -------------------------------------------------------------
- CALCCRC:
- movem.l d1-d3/a0,-(a7)
- bra.s CRCNEXT
-
- CRCLOOP:
- move.b (a0)+,d3
- move.w d0,d2
- lsr.w #8,d0
- eor.b d3,d0
- move.w d0,d3
- lsr.w #4,d0
- eor.w d3,d0
- move.w d0,d3
- lsl.w #4,d0
- eor.w d2,d0
- lsl.w #3,d0
- eor.w d3,d0
- lsl.w #5,d0
- eor.w d3,d0
-
- CRCNEXT:
- dbra d1,CRCLOOP
- movem.l (a7)+,d1-d3/a0
- rts
-
- ; --------------------------------------------------------------
- ; Convert d0.w from MFM to ASCII. Return value in d0.b
- ; --------------------------------------------------------------
- MFMASCD0:
- movem.l d1/a0,-(a7)
-
- andi.w #%0101010101010101,d0
- move.b d0,d1
- lsr.w #7,d0
- or.b d1,d0
- lea MFMASCTB(pc),a0
- move.b 0(a0,d0.w),d0
-
- movem.l (a7)+,d1/a0
- rts
-
- ; MFM to ASCII table
-
- MFMASCTB:
- DC.B $00,$01,$10,$11,$02,$03,$12,$13,$20,$21,$30,$31,$22,$23,$32,$33
- DC.B $04,$05,$14,$15,$06,$07,$16,$17,$24,$25,$34,$35,$26,$27,$36,$37
- DC.B $40,$41,$50,$51,$42,$43,$52,$53,$60,$61,$70,$71,$62,$63,$72,$73
- DC.B $44,$45,$54,$55,$46,$47,$56,$57,$64,$65,$74,$75,$66,$67,$76,$77
- DC.B $08,$09,$18,$19,$0A,$0B,$1A,$1B,$28,$29,$38,$39,$2A,$2B,$3A,$3B
- DC.B $0C,$0D,$1C,$1D,$0E,$0F,$1E,$1F,$2C,$2D,$3C,$3D,$2E,$2F,$3E,$3F
- DC.B $48,$49,$58,$59,$4A,$4B,$5A,$5B,$68,$69,$78,$79,$6A,$6B,$7A,$7B
- DC.B $4C,$4D,$5C,$5D,$4E,$4F,$5E,$5F,$6C,$6D,$7C,$7D,$6E,$6F,$7E,$7F
- DC.B $80,$81,$90,$91,$82,$83,$92,$93,$A0,$A1,$B0,$B1,$A2,$A3,$B2,$B3
- DC.B $84,$85,$94,$95,$86,$87,$96,$97,$A4,$A5,$B4,$B5,$A6,$A7,$B6,$B7
- DC.B $C0,$C1,$D0,$D1,$C2,$C3,$D2,$D3,$E0,$E1,$F0,$F1,$E2,$E3,$F2,$F3
- DC.B $C4,$C5,$D4,$D5,$C6,$C7,$D6,$D7,$E4,$E5,$F4,$F5,$E6,$E7,$F6,$F7
- DC.B $88,$89,$98,$99,$8A,$8B,$9A,$9B,$A8,$A9,$B8,$B9,$AA,$AB,$BA,$BB
- DC.B $8C,$8D,$9C,$9D,$8E,$8F,$9E,$9F,$AC,$AD,$BC,$BD,$AE,$AF,$BE,$BF
- DC.B $C8,$C9,$D8,$D9,$CA,$CB,$DA,$DB,$E8,$E9,$F8,$F9,$EA,$EB,$FA,$FB
- DC.B $CC,$CD,$DC,$DD,$CE,$CF,$DE,$DF,$EC,$ED,$FC,$FD,$EE,$EF,$FE,$FF
-
- ; --------------------------------------------------------------
- ; Convert byte d0.b, from ASCII to MFM. Return value in d0.w
- ; --------------------------------------------------------------
- ASCMFMD0:
- movem.l d1/a0,-(a7)
-
- move.l AV.DSKV,a0
- move.w FV.LASTBit(a0),d1
- lsl.w #8,d1
- move.b d0,d1
- move.w d1,FV.LASTBit(a0)
-
- lea ASCMFMTB(pc),a0
- lsr.w #4,d1
- andi.w #$1F,d1
- move.b 0(a0,d1.w),d1
- lsl.w #8,d1
- andi.w #$1F,d0
- move.b 0(a0,d0.w),d1
- move.w d1,d0
-
- movem.l (a7)+,d1/a0
- rts
-
- ; ASCII to MFM table
-
- ASCMFMTB:
- DC.B $AA,$A9,$A4,$A5,$92,$91,$94,$95,$4A,$49,$44,$45,$52,$51,$54,$55
- DC.B $2A,$29,$24,$25,$12,$11,$14,$15,$4A,$49,$44,$45,$52,$51,$54,$55
-
- ; --------------------------------------------------------------
- ; Select drive d0.w and switch on motor
- ; eq = no errors, ne = drive error (held in d0)
- ; --------------------------------------------------------------
- SEL_DRV:
- movem.l d2/a3-a4,-(a7)
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- and.w #$3,d0 ; Only drives 0-3.
-
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- bclr d0,FV.RDYFLag(a3) ; set drive not ready
-
- ; switch to this drive
-
- move.w d0,FV.REQDRive(a3) ; switch drives
-
- ; check if motor already running
-
- tst.w DV.TIMEOut(a4)
- bne.s SEL_CK_CHG
-
- ; select new drive
-
- bsr hw_MTR_ON
-
- ; check if drive motor can reach speed
-
- bsr hw_IS_DRVRDY
- ; bne SEL_DRV_NF ; drive no good
-
- SEL_CK_CHG:
-
- ; check for disk change
-
- bsr hw_IS_CHG
- bne.s SEL_CHG_NO
-
- bset d0,FV.CNGFLag(a3) ; indicate disk not changed
-
- SEL_CHG_NO:
-
- ; check if there's a disk in the drive
-
- bsr hw_IS_CHG
- beq.s SEL_DRV_NF
-
- ; select correct side for this drive
-
- SEL_DRV_OK:
- move.w DV.SIDE(a4),d1
- bsr hw_SEL_SIDE
-
- move.w FV.REQDRive(a3),d0
- bset d0,FV.RDYFLag(a3) ; set drive ready
-
- moveq #0,d0 ; reset error number
- bra.s SEL_DRVX
-
- SEL_DRV_NF:
- bclr d0,FV.RDYFLag(a3) ; set not drive ready
- moveq #-7,d0 ; not found
-
- ; set pending motor off for specified drive to 4 seconds
-
- SEL_DRVX:
- move.w #200,DV.TIMEOut(a4)
-
- tst.b d0
- movem.l (a7)+,d2/a3-a4
- rts
-
- ; -------------------------------------------------------------
- ; Select side d0.w
- ; eq = no errors, ne = drive error (held in d0)
- ; -------------------------------------------------------------
- SEL_SIDE:
- movem.l d1-d2/a3-a4,-(a7)
-
- move.w d0,d1 ; save side to set
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- move.w FV.REQDRive(a3),d0
- and.w #$3,d0 ; only drives 0-3
-
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- cmp.w DV.SIDE(a4),d1 ; Same side?
- beq.s SELSIDE1
-
- bsr FLUSH_BUFF ; flush buffer
- bne.s SELSIDEX
-
- SELSIDE1:
- move.w d1,DV.SIDE(a4)
- move.w FV.REQDRive(a3),d0
- bsr hw_SEL_SIDE
-
- SELSIDE_OK:
- moveq #0,d0
-
- SELSIDEX:
- tst.b d0
- movem.l (a7)+,d1-d2/a3-a4
- rts
-
- ; -------------------------------------------------------------
- ; Go to track d0.w
- ; eq = no errors, ne = drive error (held in d0)
- ; -------------------------------------------------------------
- GO_TRACK:
- movem.l d1-d2/a3-a4,-(a7)
-
- move.w d0,d1 ; save track
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- move.w FV.REQDRive(a3),d0
- and.w #$3,d0 ; only drives 0-3
-
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- cmp.w DV.TRACK(a4),d1 ; Same track?
- beq.s GO_TRACK1
-
- bsr FLUSH_BUFF ; flush buffer
- bne.s GO_TRACKX
-
- GO_TRACK1:
- move.w FV.REQDRive(a3),d0
- bclr d0,FV.CNGFLag(a3) ; clear disk change flag
-
- tst.b d1 ; Track 0 ?
- bne.s ANYTRACK
-
- bsr hw_GO_TK0
- clr.w DV.TRACK(a4)
-
- bra.s GO_TRACK_OK
-
- ANYTRACK:
- move.w DV.TRACK(a4),d2
- cmp.b d2,d1
- bgt.s SI_TRACK
- blt.s SO_TRACK
-
- GO_TRACK_OK:
- moveq #0,d0
-
- GO_TRACKX:
- tst.b d0
- movem.l (a7)+,d1-d2/a3-a4
- rts
-
- SI_TRACK:
- bsr hw_STEP_IN
- addq.w #1,DV.TRACK(a4)
- bra.s ANYTRACK
-
- SO_TRACK:
- bsr hw_STEP_OUT
- subq.w #1,DV.TRACK(a4)
- bra.s ANYTRACK
-
- ; -------------------------------------------------------------
- ; Check if drive FV.REQDRive is ready. Return status in d0.l
- ; -------------------------------------------------------------
- CKRDY:
- movem.l d1/a3,-(a7)
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- move.w FV.REQDRive(a3),d0
- btst d0,FV.CNGFLag(a3)
- bne.s CKRDYTST
-
- btst d0,FV.RDYFLag(a3)
- bne.s CKRDYOK
-
- CKRDYTST:
- bsr SEL_DRV
- beq.s CKRDYOK
-
- CKRDYNOT:
- moveq #-1,d0
-
- movem.l (a7)+,d1/a3
- rts
-
- CKRDYOK:
- moveq #0,d0
-
- movem.l (a7)+,d1/a3
- rts
-
- ; -------------------------------------------------------------
- ; return status of writeprotect signal in d0.l for FV.REQDRive
- ; -------------------------------------------------------------
- WPRO:
- movem.l a3,-(a7)
-
- move.l AV.DSKV,a3 ; address of disk vars, a3
-
- move.w FV.REQDRive(a3),d0
- bsr hw_IS_PRO
-
- beq.s WPRO_YES
-
- WPRO_NO:
- moveq #0,d0
- bra.s WPRO_X
-
- WPRO_YES:
- moveq #1,d0
-
- WPRO_X:
- movem.l (a7)+,a3
- rts
-
- ; -------------------------------------------------------------
- ; return status of diskchange signal in d0.l for FV.REQDRive
- ; -------------------------------------------------------------
- CHNG:
- movem.l d2/a3-a5,-(a7)
-
- move.l AV.DSKV,a3 ; address of disk vars, a3
-
- move.w FV.REQDRive(a3),d0
- and.w #$3,d0 ; only drives 0-3
-
- btst d0,FV.CNGFLag(a3)
- bne.s CHNG_YES
-
- bsr hw_IS_CHG
- beq.s CHNG_YES
-
- CHNG_NO:
- bclr d0,FV.CNGFLag(a3) ; indicate disk not changed
- moveq #0,d0
- movem.l (a7)+,d2/a3-a5
- rts
-
- CHNG_YES:
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- bsr CHNG_IT
-
- moveq #1,d0
- movem.l (a7)+,d2/a3-a5
- rts
-
- ; -------------------------------------------------------------
- ; provide Diskchange signal for non standard drive d0
- ; -------------------------------------------------------------
- DSKCNG:
- movem.l d0/d2/a3-a5,-(a7)
-
- move.l AV.DSKV,a3 ; address of disk vars, a3
-
- and.w #$3,d0 ; Only drives 0-3.
-
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- move.w d0,-(a7)
- bsr FLUSH_BUFF ; just in case
- move.w (a7)+,d0
-
- bsr CHNG_IT
-
- movem.l (a7)+,d0/d2/a3-a5
- rts
-
- CHNG_IT:
- move.l DV.SIDE0buff(a4),a5 ; address of vars, side 0
- cmp.w AB.DRIVE(a5),d0 ; is buffer owned by drive?
- bne.s DSKCNG2 ; no it isn't!
-
- move.w #-1,AB.DRIVE(a5) ; set impossible disk
- move.w #-1,AB.SIDE(a5) ; set impossible side
- move.w #-1,AB.TRACK(a5) ; set impossible track
- clr.w AB.PENDWflag(a5) ; clear pending write
- move.w #511,AB.BADFLag(a5) ; sectors all bad
-
- DSKCNG2:
- move.l DV.SIDE1buff(a4),a5 ; address of vars, side 1
- cmp.w AB.DRIVE(a5),d0 ; is buffer owned by drive?
- bne.s DSKCNG3 ; no it isn't!
-
- move.w #-1,AB.DRIVE(a5) ; set impossible disk
- move.w #-1,AB.SIDE(a5) ; set impossible side
- move.w #-1,AB.TRACK(a5) ; set impossible track
- clr.w AB.PENDWflag(a5) ; clear pending write
- move.w #511,AB.BADFLag(a5) ; sectors all bad
-
- DSKCNG3:
- bset d0,FV.CNGFLag(a3) ; set disk changed
- bclr d0,FV.RDYFLag(a3) ; set drive not ready
-
- bsr hw_DRV_TYP
- move.l d0,DV.TYPE(a4)
-
- rts
-
- ; -------------------------------------------------------------
- ; 50 Hz interrupt server (now changed to polled task)
- ; switch off motor if requested
- ; Flush writebuffer before motor_off
- ; -------------------------------------------------------------
- POLSERV:
- movem.l d0/d2/a3-a5,-(a7)
-
- move.l AV.DSKV,a3 ; Address of disk vars, a3
-
- POLSERV1:
- bset.b #7,FV.POLLActiv(a3) ; schedular already active?
- bne.s POLX ; if so, then ignore
-
- move.w FV.MAXDRive(a3),d0 ; check timeout, all drives
-
- STPFLPLP:
- bsr TESTSTOP
- dbra d0,STPFLPLP
-
- bclr.b #7,FV.POLLActiv(a3) ; mark schedular inactive
-
- POLX:
- movem.l (a7)+,d0/d2/a3-a5
- rts
-
- TESTSTOP:
- move.w d0,d2 ; Address of drive vars for
- mulu.w #DV_LEN,d2 ; required drive in a4
- lea FV.DRVVArs(a3,d2.w),a4
-
- move.w DV.TIMEOut(a4),d2 ; anything to do?
- beq.s INTEX
-
- subq.w #1,d2
- move.w d2,DV.TIMEOut(a4)
- tst.w d2
- bne INTEX
-
- move.w d0,d2
- bsr FLUSH_BUFF
- move.w d2,d0
-
- INTEX1:
- bsr hw_MTR_OFF
-
- INTEX:
- rts
-
- ; -------------------------------------------------------------
- FLUSHALL:
- movem.l d0/d2,-(a7)
-
- move.w FV.MAXDRive(a3),d0
-
- FLSHALLLP:
- move.w d0,d2
- bsr FLUSH_BUFF
- move.w d2,d0
- dbra d0,FLSHALLLP
-
- movem.l (a7)+,d0/d2
- rts
-
- ; -------------------------------------------------------------
- ; wait for no blitter activity, or a maximum of 40ms.
- ; -------------------------------------------------------------
- SCR_OFF:
- movem.l d0-d1,-(a7)
-
- move.l #39,d1 ; set count for 40 ms
-
- sof_LUP1:
- bsr hw_BEG_TIMING
-
- sof_LUP2:
- btst.b #6,DMACONR ; wait blitter not busy
- beq.s sof_X
-
- bsr hw_IS_TIMING
- beq.s sof_LUP2
-
- dbra d1,sof_LUP1
-
- sof_X:
- movem.l (a7)+,d0-d1
- rts
-
- ; -------------------------------------------------------------
- ; ROUTINES THAT HIT THE HARDWARE DIRECTLY
- ; -------------------------------------------------------------
-
- DISKCOPY:
- movem.l d1-d3/d7/a0/a3,-(a7)
-
- moveq #1,d0 ; drive 1
- bsr hw_IS_PRO
- bne.s DC_CONT
-
- moveq #ERR.RO,d3
- bra DC_EXIT
-
- DC_CONT:
- trap #0
- or.w #$0700,sr ; disable interrupts
-
- bsr SCR_OFF ; wait for blitter
-
- move.l AV.DSKV,a3
- move.w FV.FLAGS(a3),d7 ; save FV.FLAGS
- move.w #%0011000000000000,FV.FLAGS(a3) ; indx R&W, no SYNC
-
- moveq #0,d0 ; drive 0
- bsr hw_GO_TK0
-
- bsr hw_MTR_ON
- bsr hw_IS_DRVRDY
- beq.s DC_CONT1
-
- moveq #ERR.NF,d3
- bra.s DC_X0
-
- DC_CONT1:
- moveq #1,d0 ; drive 1
- bsr hw_GO_TK0
-
- bsr hw_MTR_ON
- bsr hw_IS_DRVRDY
- beq.s DC_CONT2
-
- moveq #ERR.NF,d3
- bra.s DC_X1
-
- DC_CONT2:
- lea MFMBUFFER,a0 ; buffer address
-
- ; start in earnest
-
- moveq #0,d2 ; track number
-
- DC_CPY_LUP:
- moveq #0,d0 ; drive 0
- moveq #0,d1 ; side number
- bsr hw_RD_DSK ; read track
-
- moveq #1,d0 ; drive 1
- bsr hw_WR_DSK ; write track
-
- moveq #0,d0 ; drive 0
- moveq #1,d1 ; side number
- bsr hw_RD_DSK ; read track
-
- bsr hw_STEP_IN
-
- moveq #1,d0 ; drive 1
- bsr hw_WR_DSK ; write track
-
- bsr hw_STEP_IN
-
- addq #1,d2
- cmpi.b #80,d2
- bne.s DC_CPY_LUP
-
- moveq #ERR.OK,d3
- DC_X1:
- moveq #1,d0 ; drive 1
- bsr hw_GO_TK0
- bsr hw_MTR_OFF
- bsr DSKCNG
- DC_X0:
- moveq #0,d0 ; drive 0
- bsr hw_GO_TK0
- bsr hw_MTR_OFF
- bsr DSKCNG
-
- move.w d7,FV.FLAGS(a3)
-
- move.w (sp)+,sr
-
- DC_EXIT:
- move.l d3,d0
- movem.l (a7)+,d1-d3/d7/a0/a3
- rts
-
- ; -------------------------------------------------------------
- ; Wait for d0 x 1000th of a second
- ; -------------------------------------------------------------
- hw_TIMER:
- movem.l d0,-(a7)
-
- bra.s hw_TIMER3
-
- hw_TIMER1:
- bsr hw_BEG_TIMING
-
- hw_TIMER2:
- bsr hw_IS_TIMING
- beq.s hw_TIMER2
-
- hw_TIMER3:
- dbra d0,hw_TIMER1
-
- movem.l (a7)+,d0
- rts
-
- ; -------------------------------------------------------------
- ; Set timer A for one 1000th of a second
- ; -------------------------------------------------------------
- hw_BEG_TIMING:
- move.b #$CC,CIAB_TALO ; and set counter to 716
- move.b #$02,CIAB_TAHI
- move.b #9,CIAB_CRA ; set timer to OneShot &
- ; set the start bit
-
- rts
-
- ; -------------------------------------------------------------
- ; Check if timer A is still going
- ; eq = still timing, ne = run down
- ; -------------------------------------------------------------
- hw_IS_TIMING:
- movem.l d0-d1,-(a7)
-
- move.b CIAB_CRA,d0
- eor.b #1,d0
- and.b #1,d0
-
- movem.l (a7)+,d0-d1
- rts
-
- ; -------------------------------------------------------------
- ; Wait until an INDEX interrupt is requested, or for 2 seconds
- ; ne = INDEX found, eq = no INDEX found
- ; -------------------------------------------------------------
- hw_WTIDX:
- movem.l d0-d1,-(a7)
-
- move.b CIAB_ICR,d0 ; read & reset int flg
- or.b AV.CIAB_ICR,d0
- bclr #4,d0 ; clear previous indx int
- move.b d0,AV.CIAB_ICR ; store for another program
-
- move.l #1999,d1 ; set count for 2000 ms
-
- hw_WTIDX_LUP1:
- bsr hw_BEG_TIMING
-
- hw_WTIDX_LUP2:
- move.b CIAB_ICR,d0 ; read CIA-B ICR
- or.b AV.CIAB_ICR,d0
- move.b d0,AV.CIAB_ICR ; store for another program
-
- bclr #4,d0 ; was it index ?
- bne hw_WTIDX_X ; ...yes
-
- hw_WTIDX_CONT:
- bsr hw_IS_TIMING
- beq.s hw_WTIDX_LUP2
-
- dbra d1,hw_WTIDX_LUP1
-
- hw_WTIDX_X:
- addq.w #1,d1 ; set flags
- tst.w d1
-
- movem.l (a7)+,d0-d1
-
- rts
-
- ; -------------------------------------------------------------
- ; Wait from disk DMA finished signal or for 0.5 seconds
- ; ne = DMA finished, eq = DMA not complete
- ; -------------------------------------------------------------
- hw_WTDSKDMA:
- movem.l d0-d1,-(a7)
-
-
- move.l #499,d1 ; set count for 500 ms
-
- hw_WTDMA_LUP1:
- bsr hw_BEG_TIMING
-
- hw_WTDMA_LUP2:
- move.w INTREQR,d0
- btst #1,d0 ; is disk DMA finished?
- bne.s hw_WTDSKDMA_X
-
- bsr hw_IS_TIMING
- beq.s hw_WTDMA_LUP2
-
- dbra d1,hw_WTDMA_LUP1
-
- hw_WTDSKDMA_X:
- move.w #$4000,DSKLEN ; stop disk DMA
-
- move.w #$0002,INTREQ ; clear interrupt flag
-
- addq.w #1,d1 ; set flags
- tst.w d1
-
- movem.l (a7)+,d0-d1
-
- rts
-
- ; --------------------------------------------------------------
- ; Read MFM track from disk to buffer at a0.l
- ; Pass drive number in d0.w, side in d1.w, track number in d2.w
- ; eq = Track read OK, ne = disk error
- ; --------------------------------------------------------------
- hw_RD_DSK:
- movem.l d0-d3/a3,-(a7)
-
- moveq #ERR.NF,d3
-
- bsr hw_MTR_ON
- ; bsr hw_IS_DRVRDY
- ; bne hw_RD_DSK5
-
- bsr hw_SEL_SIDE ; select correct side
- bsr hw_SEL_DRV ; select drive
-
- move.w #$4000,DSKLEN ; stop disk DMA
- move.w #$8010,DMACON ; enable disk DMA
- move.l a0,DSKPTH ; start of buffer
- move.w #$6600,ADKCON ; PRECOMP=0, GCR SYNC off, WORDSYNC off
- move.w #$9100,ADKCON ; MFMPREC for MFM, 2°s/bit
-
- cmp.w #40,d2 ; if it is a high track,
- blt.s hw_RD_DSK1 ; we need a
- move.w #$A000,ADKCON ; 140 ns precompensation
-
- hw_RD_DSK1:
- move.l AV.DSKV,a3
- move.w FV.FLAGS(a3),d2
-
- move.w #(((TLEN+1324)>>1)&$3FFF)|$8000,d1
-
- btst #12,d2 ; branch if index enabled
- bne.s hw_RD_DSK2
-
- btst #11,d2 ; branch if word SYNC disabled
- beq.s hw_RD_DSK4
-
- move.w #$8400,ADKCON ; SYNC on
- move.w #$4489,DSKSYNC ; sync word
-
- bra.s hw_RD_DSK4
-
- ; do disk read via index interrupt
-
- hw_RD_DSK2:
- move.w #((TLEN>>1)&$3FFF)|$8000,d1
-
- btst #11,d2 ; branch if word SYNC disabled
- beq.s hw_RD_DSK3
-
- move.w #$8400,ADKCON ; SYNC on
- move.w #$4489,DSKSYNC ; sync word
- move.w #(((TLEN-376)>>1)&$3FFF)|$8000,d1
-
- hw_RD_DSK3:
-
- bsr hw_WTIDX ; wait for index
- beq.s hw_RD_DSK5 ; branch on error
-
- ; do disk read
-
- hw_RD_DSK4:
- move.w d1,DSKLEN ; initiate disk operation
- move.w d1,DSKLEN
-
- move.w #$0002,INTREQ ; clear previous interrupt
- ; requests from disk DMA
-
- ; wait for operation to finish, then exit
-
- bsr hw_WTDSKDMA ; wait, until disk written
- beq.s hw_RD_DSK5 ; branch on error
-
- moveq #ERR.OK,d3 ; signal read error
-
- hw_RD_DSK5:
- bsr hw_DESEL_DRV ; deselect drive
-
- tst.l d3 ; set flags
-
- movem.l (a7)+,d0-d3/a3
- rts
-
- ; -------------------------------------------------------------
- ; Write MFM track to disk from buffer at a0.l
- ; Pass drive number in d0.w, track number in d1.w
- ; Requires you to have set up an interrupt server that acts
- ; on the index pulse and begins the actual disk write and DMA
- ; -------------------------------------------------------------
- hw_WR_DSK:
- movem.l d0-d3/a3,-(a7)
-
- move.w sr,-(a7)
- ori.w #$0700,sr
-
- moveq #ERR.NF,d3
-
- bsr hw_MTR_ON
- ; bsr hw_IS_DRVRDY
- ; bne hw_WR_DSK4
-
- bsr hw_SEL_SIDE ; select side
- bsr hw_SEL_DRV ; select drive
-
- move.w #$4000,DSKLEN ; stop disk DMA
- move.w #$8010,DMACON ; enable disk DMA
- move.l a0,DSKPTH ; start of buffer
- move.w #$6600,ADKCON ; PRECOMP=0, MFM , no SYNC
- move.w #$9100,ADKCON ; MFMPREC for MFM, 2°s/bit
-
- cmp.w #40,d2 ; if it is a high track,
- blt.s hw_WR_DSK1 ; we need a
- move.w #$A000,ADKCON ; 140 ns precompensation
-
- hw_WR_DSK1:
- move.l AV.DSKV,a3
- move.w FV.FLAGS(a3),d1
-
- btst #13,d1 ; branch if index disabled
- beq hw_WR_DSK2
-
- ; do disk write via index interrupt
-
- bsr hw_WTIDX ; wait for index
- beq.s hw_WR_DSK4 ; branch on error
-
- ; do disk write
-
- hw_WR_DSK2:
- move.w #((WLEN>>1)&$3FFF)|$C000,d1
-
- move.w d1,DSKLEN ; initiate disk operation
- move.w d1,DSKLEN
-
- move.w #$0002,INTREQ ; clear previous interrupt
- ; requests from disk DMA
-
- ; wait for operation to finish, then exit
-
- hw_WR_DSK3:
- bsr hw_WTDSKDMA ; wait, until disk written
- beq.s hw_WR_DSK4 ; branch on error
-
- moveq #ERR.OK,d3
-
- hw_WR_DSK4:
- bsr hw_DESEL_DRV ; deselect drive
-
- tst.l d3
-
- move.w (a7)+,sr
-
- movem.l (a7)+,d0-d3/a3
- rts
-
- ; -------------------------------------------------------------
- ; deselect all drives
- ; -------------------------------------------------------------
- hw_DESEL_ALL:
- or.b #%01111000,CIAB_PRB ; deselect all drives
-
- rts
-
- ; -------------------------------------------------------------
- ; Select disk d0.b
- ; -------------------------------------------------------------
- hw_SEL_DRV:
- and.w #$3,d0 ; Only drives 0-3.
-
- movem.l d0,-(a7)
-
- addq.b #3,d0
- bclr.b d0,CIAB_PRB ; select drive
-
- movem.l (a7)+,d0
- rts
-
- ; -------------------------------------------------------------
- ; Deselect disk d0.b
- ; -------------------------------------------------------------
- hw_DESEL_DRV:
- and.w #$3,d0 ; Only drives 0-3.
-
- movem.l d0,-(a7)
-
- addq.b #3,d0
- bset.b d0,CIAB_PRB ; deselect drive
-
- movem.l (a7)+,d0
- rts
-
- ; -------------------------------------------------------------
- ; switch on motor for drive d0.w
- ; -------------------------------------------------------------
- hw_MTR_ON:
- and.w #$3,d0 ; Only drives 0-3.
-
- bsr hw_DESEL_ALL
- bclr #7,CIAB_PRB ; switch on motor
- bsr hw_SEL_DRV
- bsr hw_DESEL_DRV
-
- rts
-
- ; -------------------------------------------------------------
- ; switch off motor for drive d0.w
- ; -------------------------------------------------------------
- hw_MTR_OFF:
- and.w #$3,d0 ; Only drives 0-3.
-
- bsr hw_DESEL_ALL
- bset #7,CIAB_PRB ; switch off motor
- bsr hw_SEL_DRV
- bsr hw_DESEL_DRV
-
- rts
- ; -------------------------------------------------------------
- ; select side d1.b for drive d0.w
- ; -------------------------------------------------------------
- hw_SEL_SIDE:
- and.w #$3,d0 ; Only drives 0-3.
- bsr hw_DESEL_ALL
-
- btst.b #0,d1
- beq.s hw_SEL_SID0
-
- hw_SEL_SID1:
- bclr #2,CIAB_PRB ; select side 1
- bra.s hw_SEL_SIDX
-
- hw_SEL_SID0:
- bset #2,CIAB_PRB ; select side 0
-
- hw_SEL_SIDX:
- bsr hw_SEL_DRV
- bsr hw_DESEL_DRV
-
- rts
-
- ; -------------------------------------------------------------
- ; Step in one track (increase track number) on drive d0.w
- ; -------------------------------------------------------------
- hw_STEP_IN:
- movem.l d1,-(a7)
-
- and.w #$3,d0 ; Only drives 0-3.
- bsr hw_DESEL_ALL
-
- bsr hw_SEL_DRV
-
- bclr #1,CIAB_PRB ; reset direction bit
-
- bset #0,CIAB_PRB ; set diskstep bit
- bclr #0,CIAB_PRB ; reset diskstep bit
- bset #0,CIAB_PRB ; set diskstep bit
-
- bsr hw_DESEL_DRV
-
- moveq #4,d1 ; set count for 5ms
-
- hw_SI_LUP1:
- bsr hw_BEG_TIMING
-
- hw_SI_LUP2:
- bsr hw_IS_TIMING
- beq.s hw_SI_LUP2
-
- dbra d1,hw_SI_LUP1
-
- hw_SI_X:
- movem.l (a7)+,d1
- rts
-
- ; -------------------------------------------------------------
- ; Step out one track (decrease track number) on drive d0.w
- ; -------------------------------------------------------------
- hw_STEP_OUT:
- movem.l d1,-(a7)
-
- and.w #$3,d0 ; Only drives 0-3.
- bsr hw_DESEL_ALL
-
- bsr hw_SEL_DRV
-
- bset #1,CIAB_PRB ; set direction bit
-
- bset #0,CIAB_PRB ; set diskstep bit
- bclr #0,CIAB_PRB ; reset diskstep bit
- bset #0,CIAB_PRB ; set diskstep bit
-
- bsr hw_DESEL_DRV
-
- moveq #4,d1 ; set count for 5ms
-
- hw_SO_LUP1:
- bsr hw_BEG_TIMING
-
- hw_SO_LUP2:
- bsr hw_IS_TIMING
- beq.s hw_SO_LUP2
-
- dbra d1,hw_SO_LUP1
-
- hw_SO_X:
- movem.l (a7)+,d1
- rts
-
- ; -------------------------------------------------------------
- ; Find track zero on drive d0.w
- ; -------------------------------------------------------------
- hw_GO_TK0:
- movem.l d1,-(a7)
-
- moveq #84,d1 ; maximum 84 tracks to step
- hw_GT0_LUP:
- bsr hw_IS_TK0 ; already track 0?
- beq.s hw_GT0_X
- bsr hw_STEP_OUT ; step a little closer
- dbra d1,hw_GT0_LUP
-
- hw_GT0_X:
- movem.l (a7)+,d1
- rts
-
- ; -------------------------------------------------------------
- ; return whether drive d0.w is at track zero
- ; eq = is at track zero, ne = is not at track zero
- ; -------------------------------------------------------------
- hw_IS_TK0:
- movem.l d0-d1,-(a7)
-
- and.w #$3,d0 ; Only drives 0-3.
- bsr hw_DESEL_ALL
-
- bsr hw_SEL_DRV
- move.b CIAA_PRA,d1
- bsr hw_DESEL_DRV
-
- andi.b #16,d1
-
- movem.l (a7)+,d0-d1
- rts
-
- ; -------------------------------------------------------------
- ; wait until drive has reached speed, or for a maximum of
- ; 500 milliseconds.
- ; eq = drive has reached speed, ne = drive is duff
- ; -------------------------------------------------------------
- hw_IS_DRVRDY:
- movem.l d0-d1,-(a7)
-
- ; wait for motor to reach speed
-
- move.w #500,d1 ; set counter for 500ms
-
- hw_IS_DRVRDY1:
- bsr hw_BEG_TIMING
-
- hw_IS_DRVRDY2:
- ; bsr hw_IS_RDY
- ; beq.s hw_IS_DRVRDY3
-
- bsr hw_IS_TIMING
- beq.s hw_IS_DRVRDY2
-
- dbra d1,hw_IS_DRVRDY1
-
- ; bsr hw_MTR_OFF
-
- ; moveq #-1,d0
- ; bra.s hw_IS_DRVRDYX
-
- hw_IS_DRVRDY3:
- moveq #0,d0
-
- hw_IS_DRVRDYX:
- movem.l (a7)+,d0-d1
- rts
-
- ; -------------------------------------------------------------
- ; return motor ready signal for drive d0.w in zero flag
- ; eq = motor ready, ne = motor not ready
- ; -------------------------------------------------------------
- hw_IS_RDY:
- movem.l d0-d1,-(a7)
-
- and.w #$3,d0 ; Only drives 0-3.
- bsr hw_DESEL_ALL
-
- bsr hw_SEL_DRV
- move.b CIAA_PRA,d1
- bsr hw_DESEL_DRV
-
- and.b #32,d1
-
- movem.l (a7)+,d0-d1
-
- rts
-
- ; -------------------------------------------------------------
- ; return status of writeprotect signal for drive d0.w
- ; eq = protected, ne = not protected
- ; -------------------------------------------------------------
- hw_IS_PRO:
- movem.l d0-d1,-(a7)
-
- and.w #$3,d0 ; Only drives 0-3.
- bsr hw_DESEL_ALL
-
- bsr hw_SEL_DRV
- move.b CIAA_PRA,d1
- bsr hw_DESEL_DRV
-
- and.b #8,d1
-
- movem.l (a7)+,d0-d1
- rts
-
- ; -------------------------------------------------------------
- ; return status of diskchange signal for drive d0.w
- ; eq = changed, ne = not changed
- ; -------------------------------------------------------------
- hw_IS_CHG:
- movem.l d0-d1,-(a7)
-
- and.w #$3,d0 ; Only drives 0-3.
- bsr hw_DESEL_ALL
-
- bsr hw_SEL_DRV
- move.b CIAA_PRA,d1
- bsr hw_DESEL_DRV
-
- andi.b #4,d1
- bne.s hw_IS_CHGX
-
- bsr hw_STEP_IN ; clear change signal
- bsr hw_STEP_OUT
-
- tst.b d1
-
- hw_IS_CHGX:
- movem.l (a7)+,d0-d1
- rts
-
- ; -------------------------------------------------------------
- ; Return drive type for drive d0.w in d0.l
- ; -------------------------------------------------------------
- hw_DRV_TYP:
- movem.l d1-d3/a0,-(a7)
-
- addq.b #3,d0
- moveq #1,d3
- asl.b d0,d3
-
- L0F8F616:
- not.b d3
- lea CIAB_PRB,a0
- move.b #$7F,d0
- move.b d0,(a0)
- and.b d3,d0
- move.b d0,(a0)
- move.b #$FF,(a0)
- move.b d3,(a0)
- move.b #$FF,(a0)
- moveq #$1F,d1
- moveq #$0,d0
- L0F8F636:
- lsl.l #1,d0
- move.b d3,(a0)
- btst #$5,CIAA_PRA
- bne.s L0F8F648 ;*/modify beq.s L0F8F648
- bset #$0,d0
- L0F8F648:
- move.b #$FF,(a0)
- dbra d1,L0F8F636
- L0F8F650:
-
- movem.l (a7)+,d1-d3/a0
- rts
-
- ; -------------------------------------------------------------
- ; BASIC functions and procedures
- ; -------------------------------------------------------------
- PROC_DEF:
- ifnd extras
- dc.w 4
- endc
-
- ifd extras
- ifnd extras2
- dc.w 4
- endc
- ifd extras2
- dc.w 22
- endc
- endc
-
- dc.w B_DISKCOPY-*
- dc.b 8,'DISKCOPY',0
- dc.w B_MOUNT-*
- dc.b 5,'MOUNT'
- dc.w B_DSKCNG-*
- dc.b 6,'DskCng',0
-
- ifd extras
- dc.w B_hw_SEL_SIDE-*
- dc.b 11,'hw_SEL_SIDE'
- dc.w B_hw_STEP_OUT-*
- dc.b 11,'hw_STEP_OUT'
- dc.w B_hw_STEP_IN-*
- dc.b 10,'hw_STEP_IN',0
- dc.w B_hw_GO_TK0-*
- dc.b 9,'hw_GO_TK0'
- dc.w B_hw_MTR_OFF-*
- dc.b 10,'hw_MTR_OFF',0
- dc.w B_hw_MTR_ON-*
- dc.b 9,'hw_MTR_ON'
- dc.w B_hw_WR_DSK-*
- dc.b 9,'hw_WR_DSK'
- dc.w B_hw_RD_DSK-*
- dc.b 9,'hw_RD_DSK'
- dc.w B_hw_TIMER-*
- dc.b 8,'hw_TIMER'
-
- ifd extras2
- dc.w B_W_INDEX-*
- dc.b 7,'W_INDEX'
- dc.w B_R_INDEX-*
- dc.b 7,'R_INDEX'
- dc.w B_FLUSH_BUFF-*
- dc.b 10,'Flush_BUFF',0
- dc.w B_FREE_BUFF-*
- dc.b 9,'Free_BUFF'
- dc.w B_FTRACK-*
- dc.b 6,'FTrack',0
- dc.w B_WQDISK-*
- dc.b 6,'WQDisk',0
- dc.w B_RQDISK-*
- dc.b 6,'RQDisk',0
- dc.w B_WQSEC-*
- dc.b 5,'WQSec'
- dc.w B_RQSEC-*
- dc.b 5,'RQSec'
- dc.w B_SEL_DRV-*
- dc.b 7,'SEL_DRV'
- dc.w B_SEL_SIDE-*
- dc.b 8,'SEL_SIDE',0
- dc.w B_GO_TRACK-*
- dc.b 8,'GO_TRACK',0
- endc
- endc
-
- dc.w 0
-
- ifnd extras
- dc.w 4
- endc
-
- ifd extras
- ifnd extras2
- dc.w 8
- endc
- ifd extras2
- dc.w 14
- endc
- endc
-
- dc.w B_hw_DRV_TYP-*
- dc.b 10,'hw_DRV_TYP',0
-
- ifd extras
- dc.w B_hw_IS_CHG-*
- dc.b 9,'hw_IS_CHG'
- dc.w B_hw_IS_PRO-*
- dc.b 9,'hw_IS_PRO'
- dc.w B_hw_IS_RDY-*
- dc.b 9,'hw_IS_RDY'
- dc.w B_hw_IS_TK0-*
- dc.b 9,'hw_IS_TK0'
-
- ifd extras2
- dc.w B_CRC-*
- dc.b 3,'CRC'
- dc.w B_ASCMFM-*
- dc.b 6,'ASCMFM',0
- dc.w B_MFMASC-*
- dc.b 6,'MFMASC',0
- dc.w B_CHNG-*
- dc.b 4,'Chng',0
- dc.w B_WPRO-*
- dc.b 4,'WPro',0
- dc.w B_CKRDY-*
- dc.b 5,'CkRdy'
- endc
- endc
-
- dc.w 0
-
- ; -------------------------------------------------------------
- ; BASIC adaptions to M-Code procs
- ; -------------------------------------------------------------
- B_MOUNT:
- bsr FETCH_W ; get disk number
- bne B_MOUNTX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr MOUNT
-
- B_MOUNTX:
- rts
-
- ; -------------------------------------------------------------
- B_DSKCNG:
- bsr FETCH_W ; get drive number
- bne B_DSKCNGX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr DSKCNG
-
- moveq #0,d0 ; no errors
-
- B_DSKCNGX:
- rts
-
- ifd extras2
- ; -------------------------------------------------------------
- B_W_INDEX
- bsr FETCH_W ; get flag word
- bne B_W_INDEXX
-
- cmp.l a3,a5
- bne RPRT_BP
-
- movem.l a3,-(a7)
- move.l AV.DSKV,a3
-
- tst.l d1
- bne.s B_W_IDX1
-
- move.w FV.FLAGS(a3),d0
- bclr #13,d0
-
- bra.s B_W_IDX2
-
- B_W_IDX1:
- move.w FV.FLAGS(a3),d0
- bset #13,d0
-
- B_W_IDX2:
- move.w d0,FV.FLAGS(a3)
-
- movem.l (a7)+,a3
- moveq #0,d0
-
- B_W_INDEXX:
- rts
-
- ; -------------------------------------------------------------
- B_R_INDEX:
- bsr FETCH_W ; get flag word
- bne B_R_INDEXX
-
- cmp.l a3,a5
- bne RPRT_BP
-
- movem.l a3,-(a7)
- move.l AV.DSKV,a3
-
- tst.l d1
- bne.s B_R_IDX1
-
- move.w FV.FLAGS(a3),d0
- bclr #12,d0
-
- bra.s B_R_IDX2
-
- B_R_IDX1:
- move.w FV.FLAGS(a3),d0
- bset #12,d0
-
- B_R_IDX2:
- move.w d0,FV.FLAGS(a3)
-
- movem.l (a7)+,a3
- moveq #0,d0
-
- B_R_INDEXX:
- rts
-
- ; -------------------------------------------------------------
- B_CRC:
- bsr FETCH_L ; get address of data
- bne B_FLUSH_BUFFX
- move.l d1,d3
-
- bsr FETCH_L ; get length of data
- bne B_FLUSH_BUFFX
- move.l d1,d2
-
- bsr FETCH_L ; get previous CRC
- bne B_FLUSH_BUFFX
-
- cmp.l a3,a5
- bne RPRT_BP
-
- move.l d1,d0
- move.l d2,d1
- move.l d3,a0
- bsr CALCCRC
- bra RET_W
-
- ; -------------------------------------------------------------
- B_ASCMFM:
- bsr FETCH_W ; get ASCII byte
- bne B_FLUSH_BUFFX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr ASCMFMD0
- bra RET_W
-
- ; -------------------------------------------------------------
- B_MFMASC:
- bsr FETCH_W ; get MFM word
- bne B_FLUSH_BUFFX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr MFMASCD0
- bra RET_W
-
- ; -------------------------------------------------------------
- B_FLUSH_BUFF:
- bsr FETCH_W ; get disk number
- bne B_FLUSH_BUFFX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr FLUSH_BUFF
-
- B_FLUSH_BUFFX:
- rts
-
- ; -------------------------------------------------------------
- B_FREE_BUFF:
- bsr FETCH_W ; get disk number
- bne B_FREE_BUFFX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr FREE_BUFF
-
- B_FREE_BUFFX:
- rts
-
- ; -------------------------------------------------------------
- B_FTRACK:
- bsr FETCH_W ; get disk number
- bne B_FTRACKX
- move.l d1,d4
-
- bsr FETCH_W ; get side
- bne B_FTRACKX
- move.l d1,d3
-
- bsr FETCH_W ; get track number
- bne B_FTRACKX
- move.l d1,d2
-
- cmp.l a3,a5
- bne RPRT_BP
-
- move.l d4,d0
- bsr SEL_DRV
-
- move.l d3,d0
- bsr SEL_SIDE
-
- move.l d2,d0
- bsr GO_TRACK
-
- bsr FTRACK
-
- B_FTRACKX:
- rts
-
- ; -------------------------------------------------------------
- B_WQDISK:
- bsr FETCH_W ; get disk number
- bne B_WQDISKX
- move.l d1,d4
-
- bsr FETCH_W ; get side
- bne B_WQDISKX
- move.l d1,d3
-
- bsr FETCH_W ; get track number
- bne B_WQDISKX
- move.l d1,d2
-
- cmp.l a3,a5
- bne RPRT_BP
-
- move.l d4,d0
- bsr SEL_DRV
-
- move.l d3,d0
- bsr SEL_SIDE
-
- move.l d2,d0
- bsr GO_TRACK
-
- bsr WQDISK
-
- B_WQDISKX:
- rts
-
- ; -------------------------------------------------------------
- B_RQDISK:
- bsr FETCH_W ; get disk number
- bne B_RQDISKX
- move.l d1,d4
-
- bsr FETCH_W ; get side
- bne B_RQDISKX
- move.l d1,d3
-
- bsr FETCH_W ; get track number
- bne B_RQDISKX
- move.l d1,d2
-
- cmp.l a3,a5
- bne RPRT_BP
-
- move.l d4,d0
- bsr SEL_DRV
-
- move.l d3,d0
- bsr SEL_SIDE
-
- move.l d2,d0
- bsr GO_TRACK
-
- bsr RQDISK
-
- B_RQDISKX:
- rts
-
- ; -------------------------------------------------------------
- B_WQSEC:
- bsr FETCH_L ; output buffer address
- bne B_WQSECX
- move.l d1,d5
-
- bsr FETCH_W ; get disk number
- bne B_WQSECX
- move.l d1,d4
-
- bsr FETCH_W ; get side
- bne B_WQSECX
- move.l d1,d3
-
- bsr FETCH_W ; get track number
- bne B_WQSECX
- move.l d1,d2
-
- bsr FETCH_W ; get sector number
- bne B_WQSECX
-
- cmp.l a3,a5
- bne RPRT_BP
-
- move.l d4,d0
- bsr SEL_DRV
-
- move.l d3,d0
- bsr SEL_SIDE
-
- move.l d2,d0
- bsr GO_TRACK
- ; sector number in d1
- move.l d5,a1 ; output buffer address
- bsr WQSEC
-
- B_WQSECX:
- rts
-
- ; -------------------------------------------------------------
- B_RQSEC:
- bsr FETCH_L ; output buffer address
- bne B_RQSECX
-
- move.l d1,d5
-
- bsr FETCH_W ; get disk number
- bne B_RQSECX
- move.l d1,d4
-
- bsr FETCH_W ; get side
- bne B_RQSECX
- move.l d1,d3
-
- bsr FETCH_W ; get track number
- bne B_RQSECX
- move.l d1,d2
-
- bsr FETCH_W ; get sector number
- bne B_RQSECX
-
- cmp.l a3,a5
- bne RPRT_BP
-
- move.l d4,d0
- bsr SEL_DRV
-
- move.l d3,d0
- bsr SEL_SIDE
-
- move.l d2,d0
- bsr GO_TRACK
- ; sector number in d1
- move.l d5,a1 ; output buffer address
- moveq #0,d3 ; no bytes to skip
- moveq #0,d4 ; no bytes to leave
- bsr RQSEC
-
- B_RQSECX:
- rts
-
- ; -------------------------------------------------------------
- B_SEL_DRV:
- bsr FETCH_W ; get drive number
- bne B_SEL_DRVX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr SEL_DRV
-
- B_SEL_DRVX:
- rts
-
- ; -------------------------------------------------------------
- B_SEL_SIDE:
- bsr FETCH_W ; get side number
- bne B_SEL_SIDEX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr SEL_SIDE
-
- B_SEL_SIDEX:
- rts
-
- ; -------------------------------------------------------------
- B_GO_TRACK:
- bsr FETCH_W ; get track number
- bne B_GO_TRACKX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr GO_TRACK
-
- B_GO_TRACKX:
- rts
-
- ; -------------------------------------------------------------
- B_CHNG:
- bsr CHNG ; test for Disk change
- bra RET_W
-
- ; -------------------------------------------------------------
- B_WPRO:
- bsr WPRO ; test for write protect
- bra RET_W
-
- ; -------------------------------------------------------------
- B_CKRDY:
- bsr CKRDY ; check readiness of drive
- bra RET_W
-
- endc
-
- ; -------------------------------------------------------------
- ; BASIC routines that hit hit the hardware directly
- ; -------------------------------------------------------------
- B_DISKCOPY:
- moveq #0,d1 ; default channel #
- bsr GET_CH ; get channel ID
-
- cmp.l a3,a5
- bne RPRT_BP
-
- move.l AV.DSKV,a3
- cmp.w #1,FV.MAXDRive(a3)
- bge.s B_DC2
-
- lea DRVMSG(pc),a1
- bsr IOSTRG
- bra.s B_DCOK
-
- B_DC2:
- lea CPYMSG(pc),a1
- bsr IOSTRG
-
- B_DCLUP:
- moveq #IO.FBYTE,d0
- moveq #-1,d3 ; infinite timeout
- trap #3 ; fetch a byte
-
- tst.l d0
- bne.s B_DCX ; exit on error
-
- cmp.b #$0A,d1
- bne.s B_DCLUP
-
- bsr DISKCOPY ; copy disk
- bne.s B_DCX
-
- lea DONMSG(pc),a1
- bsr IOSTRG
-
- B_DCOK:
- moveq #0,d0
-
- B_DCX:
- rts
-
- ; -------------------------------------------------------------
- B_hw_DRV_TYP:
- bsr FETCH_W ; get drive number
- bne B_hw_DRV_TYPX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr hw_DRV_TYP ; test drive type
- bra RET_L
-
- B_hw_DRV_TYPX:
-
- ifd extras
-
- ; -------------------------------------------------------------
- B_hw_IS_CHG:
- bsr FETCH_W ; get drive number
- bne B_hw_SEL_SIDX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr hw_IS_CHG ; test for Disk change
- beq RET_TRU
- bra RET_FLS
-
- ; -------------------------------------------------------------
- B_hw_IS_PRO:
- bsr FETCH_W ; get drive number
- bne B_hw_SEL_SIDX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr hw_IS_PRO ; test for write protect
- beq RET_TRU
- bra RET_FLS
-
- ; -------------------------------------------------------------
- B_hw_IS_RDY:
- bsr FETCH_W ; get drive number
- bne B_hw_SEL_SIDX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr hw_IS_RDY ; check readiness of drive
- beq RET_TRU
- bra RET_FLS
-
- ; -------------------------------------------------------------
- B_hw_IS_TK0:
- bsr FETCH_W ; get drive number
- bne B_hw_SEL_SIDX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr hw_IS_TK0 ; check if at track zero
- beq RET_TRU
- bra RET_FLS
-
- ; -------------------------------------------------------------
- B_hw_SEL_SIDE:
- bsr FETCH_W ; get drive number
- bne.s B_hw_SEL_SIDX
- move.l d1,d2
-
- bsr FETCH_W ; get drive side
- bne.s B_hw_SEL_SIDX
-
- move.l d2,d0 ; drive in d0, side in d1
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr hw_SEL_SIDE
- moveq #0,d0
-
- B_hw_SEL_SIDX:
- rts
-
- ; -------------------------------------------------------------
- B_hw_STEP_OUT:
- bsr FETCH_W ; get drive number
- bne.s B_hw_STEP_OX
- move.l d1,d0
-
- bsr hw_STEP_OUT ; increase track number
- moveq #0,d0
-
- B_hw_STEP_OX:
- rts
-
- ; -------------------------------------------------------------
- B_hw_STEP_IN:
- bsr FETCH_W ; get drive number
- bne.s B_hw_STEP_IX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr hw_STEP_IN ; decrease track number
- moveq #0,d0
-
- B_hw_STEP_IX:
- rts
-
- ; -------------------------------------------------------------
- B_hw_GO_TK0:
- bsr hw_GO_TK0
- moveq #0,d0
- rts
-
- ; -------------------------------------------------------------
- B_hw_MTR_OFF:
- bsr FETCH_W ; get drive number
- bne.s B_hw_MTR_OFX
- move.l d1,d0
-
- cmp.l a3,a5
- bne RPRT_BP
-
- bsr hw_MTR_OFF ; turn of drive motor
- moveq #0,d0
-
- B_hw_MTR_OFX:
- rts
-
- ; -------------------------------------------------------------
- B_hw_MTR_ON:
- bsr FETCH_W ; get drive number
- bne.s B_hw_MTR_ONX
- move.l d1,d0
-
- cmp.l a3,a5
- bne.s RPRT_BP
-
- bsr hw_MTR_ON ; turn on drive motor
- moveq #0,d0
-
- B_hw_MTR_ONX:
- rts
-
- ; -------------------------------------------------------------
- B_hw_WR_DSK:
- bsr FETCH_L ; address of buffer in a0
- bne.s B_hw_WR_DSKX
- move.l d1,a0
-
- bsr FETCH_W ; get drive number
- bne.s B_hw_RD_DSKX
- move.l d1,d3
-
- bsr FETCH_W ; get track number
- bne.s B_hw_RD_DSKX
- move.l d1,d2
-
- bsr FETCH_W ; get side number
- bne.s B_hw_RD_DSKX
-
- move.l d3,d0 ; drive in d0, side d1, track in d2
-
- cmp.l a3,a5
- bne.s RPRT_BP
-
- bsr hw_WR_DSK ; write buffer to drive
- moveq #0,d0
-
- B_hw_WR_DSKX:
- rts
-
- ; -------------------------------------------------------------
- B_hw_RD_DSK:
- bsr FETCH_L ; address of buffer in a0
- bne.s B_hw_RD_DSKX
- move.l d1,a0
-
- bsr FETCH_W ; get drive number
- bne.s B_hw_RD_DSKX
- move.l d1,d3
-
- bsr FETCH_W ; get track number
- bne.s B_hw_RD_DSKX
- move.l d1,d2
-
- bsr FETCH_W ; get side number
- bne.s B_hw_RD_DSKX
-
- move.l d3,d0 ; drive in d0, side d1, track in d2
-
- cmp.l a3,a5
- bne.s RPRT_BP
-
- bsr hw_RD_DSK ; read to buffer from drive
- moveq #0,d0
-
- B_hw_RD_DSKX:
- rts
-
- ; -------------------------------------------------------------
- B_hw_TIMER:
-
- bsr FETCH_L ; get count in ms
- bne.s B_TIMERX
- move.l d1,d0
-
- cmp.l a3,a5
- bne.s RPRT_BP
-
- bsr hw_TIMER
- moveq #0,d0
-
- B_TIMERX:
- rts
-
- endc
-
- ; -------------------------------------------------------------
- RPRT_BP:
- moveq #ERR.BP,d0
- rts
-
- ; -------------------------------------------------------------
- CPYMSG:
- dc.w 57
- dc.b "Put SRC in flp1_ and DEST in flp2_"
- dc.b " then press <ENTER>... ",0
-
- DONMSG:
- dc.w 6
- dc.b "done.",$0A
-
- DRVMSG:
- dc.w 37
- dc.b "Sorry, you need at least two drives.",$0A,0
-
- ; -------------------------------------------------------------
- ; print string at (a1) to channel with id a0
-
- IOSTRG:
- movem.l d1-d3/a1-a2,-(a7)
-
- move.w UT.MTEXT,a2
- jsr (a2)
-
- movem.l (a7)+,d1-d3/a1-a2
- rts
-
- ifd debug
-
- ; -------------------------------------------------------------
- ; print byte d0.l as HEX to channel with id a0
-
- HEX20:
- swap d0
- bsr HEX10
- swap d0
- bsr HEX10
- rts
-
- ; -------------------------------------------------------------
- ; print byte d0.w as HEX to channel with id a0
-
- HEX10:
- ror.w #8,d0
- bsr HEX08
- rol.w #8,d0
- bsr HEX08
- rts
-
- ; -------------------------------------------------------------
- ; print byte d0.b as HEX to channel with id a0
-
- HEX08:
- movem.l d0-d1,-(a7)
-
- moveq #2,d1
-
- lsl.l #8,d1
- move.b d0,d1
- lsr.b #4,d1
- and.b #$F,d1
- add.b #'0',d1
- cmp.b #'9',d1
- ble.s HEX081
- add.b #7,d1
-
- HEX081:
- lsl.l #8,d1
- move.b d0,d1
- and.b #$F,d1
- add.b #'0',d1
- cmp.b #'9',d1
- ble.s HEX082
- add.b #7,d1
-
- HEX082:
- move.l d1,d0
- bsr IOD0
-
- movem.l (a7)+,d0-d1
- rts
-
- IOD0:
- movem.l a1,-(a7)
- move.l d0,-(a7)
- move.l a7,a1 ; address of string
- bsr IOSTRG
- move.l (a7)+,d0
- movem.l (a7)+,a1
- rts
-
- endc
-
- ; -------------------------------------------------------------
- ; Entry: A3.L pointer to first parameter
- ; A5.L pointer to last parameter
- ;
- ; Exit: A3.L updated
- ; A5.L updated
- ; D0.L...error code
- ; D1.W result
-
- FETCH_W:
- MOVEM.L A1-A2,-(A7)
-
- MOVE.W CA.GTINT,A2
- BSR.S GET_ONE
- BNE.S FETCH_WX
-
- MOVEQ #0,D1
- MOVE.W 0(A6,A1.L),D1
- ADDQ.L #2,A1
- MOVE.L A1,BV_RIP(A6)
-
- FETCH_WX:
- MOVEM.L (A7)+,A1-A2
- TST.L D0
- RTS
-
- ; --------------------------------------------------------------
- FETCH_L:
- MOVEM.L A1-A2,-(A7)
-
- MOVE.W CA.GTLIN,A2
- BSR.S GET_ONE
- BNE.S FETCH_LX
-
- MOVE.L 0(A6,A1.L),D1
- ADDQ.L #4,A1
- MOVE.L A1,BV_RIP(A6)
-
- FETCH_LX:
- MOVEM.L (A7)+,A1-A2
- TST.L D0
- RTS
-
- ; --------------------------------------------------------------
- ; This routine gets one parameter and returns it on the maths
- ; stack, pointed to by (A1).
- ;
- ; Entry: A2.L routine to call (i.e. CA.GTINT)
- ; A3.L pointer to first parameter
- ; A5.L pointer to last parameter
- ;
- ; Exit: A3.L updated
- ; A5.L updated
- ; A1.L updated pointer to top of maths stack
- ; D0.L error code
-
- GET_ONE:
- MOVEM.L D1-D6/A0/A2,-(A7)
-
- LEA 8(A3),A0
- CMP.L A0,A5
- BLT.S GET_ONEBp
-
- MOVE.L BV_RIP(A6),A1
- MOVE.L A5,-(A7)
- MOVE.L A0,A5
- MOVE.L A5,-(A7)
- JSR (A2)
- MOVEM.L (A7)+,A0/A5
-
- TST.L D0
- BNE.S GET_ONEX
-
- MOVE.L A0,A3
- MOVE.L A1,BV_RIP(A6)
-
- BRA.S GET_ONEX
-
- GET_ONEBp:
- MOVEQ #ERR.BP,D0
-
- GET_ONEX:
- MOVEM.L (A7)+,D1-D6/A0/A2
- TST.L D0
- RTS
-
- ; --------------------------------------------------------------
- ; get channel parameter
-
- ; Entry: A3.L pointer to first parameter
- ; A5.L pointer to last parameter
-
- ; Exit: A0.L CH.ID (default d1)
- ; A2.L CH.BASE
- ; A3.L updated
- ; A5.L updated
- ; D0.L error code
- ; D1.L default channel #
-
- GET_CH:
- MOVEM.L D1/D3/A1,-(A7)
-
- MOVE.L BV_RIP(A6),A1
- CMP.L A3,A5
- BEQ.S GET_CH1
-
- BTST #7,1(A6,A3.L)
- BEQ.S GET_CH1
-
- BSR FETCH_W
- BNE.S GET_CHX
-
- GET_CH1:
- MULU #$28,D1
- ADD.L BV_CHBAS(A6),D1
- CMP.L BV_CHP(A6),D1
- BGE.S GET_CHNO
-
- MOVE.L D1,A2
- MOVE.L 0(A6,A2.L),A0
- MOVE.W A0,D1
- BMI.S GET_CHNO
-
- MOVEQ #0,D0
- BRA.S GET_CHX
-
- GET_CHNO:
- MOVEQ.L #ERR.NO,D0
-
- GET_CHX:
- MOVEM.L (A7)+,D1/D3/A1
- RTS
-
- ; -------------------------------------------------------------
- ; return true or false back to BASIC
-
- RET_FLS:
- moveq #0,d0
- bra.s RET_W
-
- RET_TRU:
- moveq #1,d0
-
- ; --------------------------------------------------------------
- ; return word value to BASIC
-
- RET_W:
- move.l d0,d4
- moveq.l #2,d1
- move.w BV.CHRIX,a2
- jsr (a2)
- move.l d4,d0
-
- move.l BV_RIP(a6),a1 ; Get arith stack pointer
- subq #2,a1 ; room for 2 bytes
- move.l a1,BV_RIP(a6)
- move.w d0,0(a6,a1.l) ; Put int number on stack
- moveq.l #3,d4 ; set Integer type
- moveq.l #0,d0 ; no errors
- rts
-
- ; -------------------------------------------------------------
- ; return long Integer to BASIC
-
- RET_L:
- move.l d0,d4
- moveq.l #6,d1
- move.w BV.CHRIX,a2
- jsr (a2)
- move.l d4,d1
-
- BSR CONV_L2F
- SUBQ.L #6,BV_RIP(A6)
- MOVE.L BV_RIP(A6),A1
- MOVE.W D0,0(A6,A1.L)
- MOVE.L D1,2(A6,A1.L)
- MOVEQ.L #2,D4
- MOVEQ.L #0,D0
- RTS
-
- ; -------------------------------------------------------------
- ; convert long Integer to floating point form.
- ; Entry: d1.l = long int
- ; Exit: d0.w = exponent
- ; d1.l = mantissa
-
- CONV_L2F:
- MOVE.L D1,D0
- BEQ.S CONV_L2FX
-
- MOVE.W #$81F,D0
- MOVE.L D1,-(A7)
-
- CONV_L2F1:
- ADD.L D1,D1
- BVS.S CONV_L2F2
-
- SUBQ.W #1,D0
- MOVE.L D1,(A7)
- BRA CONV_L2F1
-
- CONV_L2F2:
- MOVE.L (A7)+,D1
-
- CONV_L2FX:
- RTS
-
- ; --------------------------------------------------------------
- */endfile
-