 lib environment
 lib bfhdr
 lib dtab
 data
 sttl CDS Winchester Drivers
 pag
 name cdsdrvr
 global cdsopen,cdsclose,cdsio,cdsint
 global cdcop,cdccl,cdcsp,cdcio,cdcrd,cdcwr

*
* driver equates and addresses
*
STATUS equ $00 request for status
SEEK equ $20 seek with verify
READ equ $50 read disk sector
WRITE equ $60 write disk with verify
VRFY equ $10 verify flag
SWPIN equ $90 swap into memory
SWPOUT equ $80 swp out of memory
*
* Controller equates
*
CMDEND equ %01000000 command end flag
CRWOK equ %00111111 sick flags
*
* Driver local data
*
cdsopt fcb 0,0 cds open table
cdslst fcb 0 CDS last command byte
cdsfup fcb 0 cds fuckup counter
BDtable fdb 0 Block Device Table address
*
* open the cds disk drive - insure the device is online, etc.
*
cdcop
cdsopen
 bsr cds_dn set up
 tst cdsopt,x already open?
 beq cdsop2
 inc cdsopt,x
 bra cdsrts
cdsop2 inc cdsopt,x set open status
 lda CDSCMD,u get disk command byte
 bmi cdsrts exit if status says online
 lda #STATUS load a status command
 jsr cdsset set command word
 sta CDSFLG,u and tag the controller
*
* wait a bit for status to come back
*
 clrb allow up to a millisecond
cdsowt lda CDSFLG,u get the flag byte from memory
 bita #$40 check for processing active
 beq cdsrts ah-ha! the disk is online
 decb decrement la counter
 bne cdsowt wait for response
 lda #EIO indicate device offline
 sta uerror stuff into user error flag
 clr cdsopt,x clear open status
cdcsp
cdsrts rts
* cds close
cdccl
cdsclose
 bsr cds_dn set up
 dec cdsopt,x dec open counter
 bpl cdsrts
 clr cdsopt,x clear open status
 rts return
*
*  Compute drive index in X and
*  drive base address in U
*
cds_dn
 subb #CDSminor compute relative drive #
 clra
 tfr d,x
 aslb get device address
 tfr d,u
 ldu CDSdev,u
 rts
*
* fire up CDS operation to initiate transfer
*
cdsio stx BDtable save Block Device Table address
 ldb bfdvn+1,y get device #
 bsr cds_dn set up for drive
 inc cdsdt+dtbusy mark busy
 ldd bfxfc,y get transfer count
 cmpd #512 is it regular block transfer?
 bne cdswap if not - do swap
 lda bfblch,y check block number range
 cmpa #$0f
 lbhi cdser if too big - error
 ora #SEEK set seek command
 ldb bfflag,y get buffer flags
 bitb #BFSPC special i/o operation (char)?
 bne cdseek if so - go do seek - no verify (formatting)
 ora #VRFY set verify bit
cdseek jsr cdsset set command word
 ldd bfblck,y get low order part of block
 std CDSADR,u stuff into address slot
 sta CDSFLG,u initiate the seek operation
 rts
*
* take care of cds swap request
*
cdswap lda bfblch,y get hi bloack address
 cmpa #$0f is it in range?
 lbhi cdser
 ora #SEEK|VRFY set seek command
 bra cdseek go do it
*
* when we get here, a seek has just completed. We need to initiate a
* DMA transfer to or from the controller.
*
cdsrw bitb #CRWOK check for seek ok
 lbne cdser nope, sick out
 inc cdsdt+dtbusy set to next mode of busy (r/w)
 ldd bfxfc,y get transfer count
 cmpd #512 is it full sector?
 bne cdswp2 if not - do swap
 ldd bfadr,y get low 16 bits of address
 std CDSADR,u set address register
 lda bfxadr,y get extended part of address
 anda #$0F mask bottom half
*
* decide whether we are doing a read or write (or swap)
*
 ldb bfflag,y get buffer flags
 bitb #BFRWF are we reading?
 beq cdswt go do write
 ora #READ set a read command
 jsr cdsset set command word
 sta CDSFLG,u tag controller to go
 rts
*
* set up for write command
*
cdswt ora #WRITE force write command
 bitb #BFSPC special i/o
 bne cdswtf
 ora #VRFY set verify mode
cdswtf jsr cdsset set command word
 sta CDSFLG,u tag controller to go
 rts
*
* Finish SWAP - Transfer data
*
cdswp2 tst SWTPCvii
 beq 0f
 pshs x save x register       * code for old dat form
 ldx bfadr,y get swap map table     * code for old dat form
cdsw25 lda 0,x+ get map byte        * code for old dat form
 cmpa DSKTRM end of list?          * code for old dat form
 beq cdsw28                         * code for old dat form
 eora #$0f make old datbox form     * code for old dat form
 sta -1,x set back in map           * code for old dat form
 bra cdsw25 repeat                  * code for old dat form
cdsw28 lda #$F3 ** Special mark for CDS ROM
 sta -1,x
 puls x reset x register      * code for old dat form
0 lda bfxadr,y get map buffer address (hi)
 anda #$f
 ora #SWPOUT set swap out mode
 ldb bfflag,y get flags
 bitb #BFRWF are we reading?
 beq cdswp3 if not - jump ahead
 ora #SWPIN set swap in mode
cdswp3 lbsr cdsset set command word
 ldd bfadr,y get map address
 std CDSADR,u send to controller
 sta CDSFLG,u flag controller
 rts return
*
* interrupt process takes hiccup from CDS-1 controller. It invokes
* the proper routine depending on the state of the DTBUSY flag.
*
* This flag may be: 0 => Ready to Not Ready
* 1 => Seek Completed
* 2 => Read or Write Completed
*
cdsint tst CDSFLG,u insure cleared interrupt
 ldb CDSCMD,u get status byte
 bitb #CMDEND command finished?
 beq cdsin1
 ldy cdsdt+dtqfl get current transaction
 beq cdsin1 jump if no transactions
 lda bfdvn+1,y get minor device #
 cmpa #CDSminor make sure device # is CDS
 blo cdsin1 jump if out of range
 cmpa #CDSminor+1
 bhi cdsin1
 lda cdsdt+dtbusy get busy status
 bne cdsin2
cdsin1 rts not busy, so return

*  check for valid returning status

cdsin2 pshs a
 lda CDSADR,u get returning command byte
 cmpa cdslst see if last command
 puls a
 beq cdsin5
 inc cdsfup increment AFU count
 sta CDSFLG,u re-tag controller with command
 rts

cdsin5 ldy cdsdt+dtqfl get first transaction
 cmpa #1 were we seeking?
 bne cdsin3 if not, transaction complete
 jmp cdsrw
cdsin3 clr cdsdt+dtbusy clear out for retry
 bitb #CRWOK any errors?
 bne cdser
cdsin4 ldd bfxfc,y get transfer coun* code for old dat form
 cmpd #512 were we swapping?        * code for old dat form
 beq 0f if not - jump ahead         * code for old dat form
 tst SWTPCvii
 beq 0f
 pshs x save index reg              * code for old dat form
 ldx bfadr,y get map address        * code for old dat form
cdsi45 lda 0,x+ get map byte        * code for old dat form
 cmpa #$F3    end of list?          * code for old dat form
 beq cdsin6                         * code for old dat form
 eora #$f make new form from old    * code for old dat form
 sta -1,x set back in map           * code for old dat form
 bra cdsi45                         * code for old dat form
cdsin6 lda DSKTRM restore map
 sta -1,x
 puls x reset index reg       * code for old dat form
0 ldx BDtable restore Block Device Table address
 jmp BDioend end of I/O operation
*
* error routine - give up forever
*
cdser lda bfflag,y get buffer flag
 ora #BFERR indicate failure
 sta bfflag,y stuff back in el flago
 clr cdsdt+dtbusy clear status
 bra cdsin4

*  set command word in CDS controller

cdsset sta CDSCMD,u stuff the command word
 anda #$F0 strip off high order bits
 sta cdslst save as last command word
 rts
 sttl CDS Winchester Character Drivers
 pag

*
* open - close - and special
*

*** Moved to save space
** cdcop jmp cdsopen same as block device
** cdccl jmp cdsclose same as block
** cdcsp rts nops here


*
* read
*

cdcrd pshs d save device number
 jsr fchgb get buffer header
 puls d reset dev number
 bsr cdcnf go configure header
 tst uerror any errors?
 beq cdcrd4
 jsr frechbf release buffer
 rts error return
cdcrd4 pshs a save task info
 orb #BFRWF set read mode
 andb #!BFSPC&$ff clear special mode
 stb bfflag,y save in buffer
 bra cdcio go do it

*
* write
*

cdcwr pshs d save device number
 jsr fchgb get buffer header
 puls d
 bsr cdcnf configure buffer
 tst uerror any errors?
 beq cdcwr4
 jsr frechbf release buffer
 rts error return
cdcwr4 pshs a save task status

*
* do character io
*

cdcio jmp fchio same as floppies

*
* configure cds character header
*

cdcnf std bfdvn,y set up device number
 ldd uicnt get transfer count
 std bfxfc,y set in header
 cmpd #512 is it valid?
 bne cdcerr error?
 jmp fchcn2 same as floppies

cdcerr lda #EIO set error
 sta uerror
 rts return
