
 opt nol
 lib environment
 lib bfhdr
 lib dtab
 lib macdefs
 opt lis
 data
 sttl Pennywise DMFP-58 Disk Controller Drivers
 pag
 name dmfpdrvr
 global dmfpint,dmfpdvn,dmfpclose,dmfpopen,dmfpio
 global dmfpcop,dmfpccl,dmfpcsp,dmfpcio,dmfpcrd,dmfpcwr

*
* Pennywise DMFP-58 Floppy/Winchester Drivers
*
MAXDEV equ 4 Max devices open simultaneously
dmfptmp fdb 0 space to "read" device size
dmfpsdn fdb 0 saved device #
BDtable fdb 0 Block Device Table address
dmfpswpt fdb 0 swap table pointer
DMFPcmd fcb 0 saved command
devtyp fdb 0,0,0,0,0,0,0,0 Drive Type
devopn fdb 0,0,0,0,0,0,0,0 Device Open Count
devdc  fdb 0,0,0,0,0,0,0,0 Device Characteristics Initialized Flag
devdct fdb dct0,dct1,dct2,dct3,dct4,dct5,dct6,dct7 device characteristics
devlun fdb $FFFF,$FFFF,$FFFF,$FFFF
       fdb $FFFF,$FFFF,$FFFF,$FFFF Drive Map (contains logical drive #
opncnt fcb 0 Count of devices open on DMFP-58
drvmap fcb 0,0,0,0 Logical -> Physical Drive Map
dctabs rzb 32*4 Device Characteristics Tables
dct0 rzb 11 Winchester Device Characteristics Tables
dct1 rzb 11
dct2 rzb 11
dct3 rzb 11
dct4 rzb 11
dct5 rzb 11
dct6 rzb 11
dct7 rzb 11
*
FD_SS fcb 0,0,15,35,0,2,0,76,0,0,8,16,0,$50,2
FD_SD fcb 0,0,15,35,0,2,0,76,0,1,8,16,1,$50,2
FD_DS fcb 0,0,15,35,0,2,0,76,1,0,8,16,0,$50,2
FD_DD fcb 0,0,15,35,0,2,0,76,1,1,8,16,1,$50,2
FD_FLEX fcb 0,0,15,35,0,0,0,76,1,0,15,26,0,$50,1
*
FDtab fdb FD_SS Single Sided/Single Density
      fdb FD_SD Single Sided/Double Density
      fdb FD_DS Double Sided/Single Density
      fdb FD_DD Double Sided/Double Density
*
HD    fcb 2,0,0,0
HD_srt fcb $86 Seek Rate
 fcb 2
HD_cyl fdb 305 Max Cyl #
HD_hd fcb 5 Max Head #
 fcb 0,17,17,0,$50,2
*
* DMFP-58 Commands and Special values
*
DMFPSDM equ $01 Set Drive Map
DMFPGDC equ $09 Get Drive Characteristics
DMFPSDC equ $0A Set Drive Characteristics
DMFPRDS equ $03 Read Sector
DMFPWRS equ $04 Write Sector
DMFPRPG equ $0B Read 4K Page
DMFPWPG equ $0C Write 4K Page
DMFPFTK equ $07 Format Track
DMFP_FT equ 32 Special count for Format Track
*
* open the disk drive - insure the device is online, etc.
*
dmfpopen
 std dmfpsdn save device #
 lbsr dmfpdvn drive select
 tst devopn,x already open?
 beq dmfpop1 no - go do open
 inc devopn,x yes - bump open count
 lbra dmfprts all done
dmfpop1 lda opncnt bump count of open devices
 cmpa #MAXDEV too many devices?
 lbge dmfpop7
 inc opncnt update count of open devices
 inc devopn,x set open status
 lda #8 force known characteristics
 jsr cpydct
 jsr getlun allocate a logical unit for drive
 jsr setdm go update drive map
 pshs x save device offset
 ldx #1 read SIR
 ldy #0
 ldd dmfpsdn restore device #
 lda #DMFPmajor make sure block read
 jsr rdbuf
 lda bfflag,y get flags
 bita #BFERR error?
 bne dmfpop8 yes - return error
 pshs y save buffer pointer
 ldx 0,s get buffer header
 ldy #dmfptmp no - read drive type
 ldu #sdenf from "density" byte in SIR
 ldd #2
 jsr cpybts
 lda dmfptmp check for winchester special info
 cmpa #$FF
 bne 00f jump if not
* -- (new) Winchester drive parameter setup
 ldx 2,s set to copy table from SIR
 ldy devdct,x
 ldx 0,s system buffer address
 ldu #swinc offset in SIR
 ldd #11
 jsr cpybts
00 puls y restore buffer pointer
 jsr freebf free buffer
 puls x
 lda dmfptmp table already set up?
 cmpa #$FF
 beq 25f yes - exit
 lda bfdvn+1,y get minor device type
 cmpa #DMFPminor+3 Floppy or Hard Disk?
 bhi 10f jump for Hard Disks
* -- Floppy disk parameter setup
 lda dmfptmp+1 get # sides
 anda #$01
 lsla *2
 adda dmfptmp get density
 sta devtyp,x save device type info
 bra 25f
* -- (old) Winchester drive parameter setup
10 lda dmfptmp pick up device type field
 cmpa #MAXDCT legal DCT index?
 bls 20f yes - jump (OK)
 lda #8 no - assume ST-506
20 jsr cpydct go copy device table
25 clr devdc,x Mark "New Device Characteristics"
 rts device opened OK
dmfpop7 lda #EDFUL too many open devices
 bra dmfpop99
dmfpop8 jsr freebf release buffer
 puls x restore device index
dmfpop9 lda #EIO indicate device offline
dmfpop99 sta uerror stuff into user error flag
 clr devopn,x clear open status
 lda #$FF de-allocate lun
 sta devlun,x
 dec opncnt fix up # open devices
dmfprts rts return
*
* Copy a device characteristics table from
* the "Winchesters" table to the internal
* drive type table
*    A - Drive type index
*    X - Device offset
*
cpydct pshs d,x,y,u
 ldy devdct,x point at device table
 ldx #MW_DCT compute device characteristics table
 leax a,x
 asla A*8
 asla
 asla
 leax a,x offset*9
 ldb #9
17 lda ,x+ copy table
 sta ,y+
 decb
 bne 17b
 clr ,y+ ** filler **
 clr ,y+
 puls d,x,y,u,pc return
*
* dmfp close
*
dmfpclose
 bsr dmfpdvn set up drive
 dec devopn,x clear open status
 bgt dmfpcl0
 clr devopn,x
 lda #$FF de-allocate lun
 sta devlun,x
 dec opncnt update # devices open
dmfpcl0
 rts return
*
* getlun - allocate a logical unit #
*    (X) - Device index
*    jsr getlun
*    devlun,x - set to appropriate LUN
*
getlun pshs d,x save registers
 clra start with LUN 0
10 ldx #devlun search for unused LUN
15 cmpa ,x++ found this LUN? (carefull!)
 beq 20f yes - must try next one
 cmpx #devlun+(8*2) end of table?
 bne 15b
 ldx 2,s yes - restore device index
 sta devlun,x
 bra 99f exit
20 inca bump LUN #
 bra 10b
99 puls d,x,pc return
*
* dmfpdvn - select DMFP drive
*   (B) - minor device #
*   return with (X) - device index
*
dmfpdvn
 cmpb #DMFPminor+7 check device number
 lbhi dmfper0 go set error
 subb #DMFPminor compute relative drive #
 lslb ** FDB tables **
 clra set up device index
 tfr d,x
 rts
*
* dmfpsdc - Set Drive Characteristics (if needed)
*         - Also sets logical drive # in CPB
*    (X) - Drive Index
*    jsr dmfpsdc
*
dmfpsdc pshs d,x,y,u save registers
 lda devlun,x get logical drive #
 sta fp_drive set logical drive # in CPB
 ldd bfxfc,y check for special mode (FLEX disk)
 cmpd #256
 bne 05f
 clr devdc,x force device to be reconfigured when normal
 ldd #FD_FLEX set special characteristics for FLEX disk
 bra 20f
05 tst devdc,x need to initialize device characteristics?
 bne 99f no - set logical unit #
 cmpx #3*2 yes - Floppy or Hard Disk
 bhi 10f jump for Hard Disk
 lda devtyp,x get Floppy type (SS, SD, DS or DD)
 lsla make word index
 ldx #FDtab pick up appropriate entry
 ldd a,x
 bra 20f
10 ldy devdct,x get device characteristics table for drive
 if 0
 bsr prt_dct
 endif
 ldd ,y++ get number of cylinders
 subd #1
 std HD_cyl
 ldb ,y+ get number of heads
 decb
 stb HD_hd
 lda 5,y get seek rate value
 pshs a
 lsra
 lsra
 lsra
 lsra
 puls b
 bitb #$04 Buffered seeks allowed?
 beq 15f
 ora #$80 yes - set flag
15 sta HD_srt set seek rate
 ldd #HD set Hard Disk Device Characteristics table
20 pshs d save buffer address
 ldx 4,s get device index
 ldb devlun,x get logical unit #
 lda #32
 mul
 ldx #dctabs copy appropriate device table
 leax d,x
 ldy 0,s
 ldb #15
25 lda ,y+
 sta ,x+
 decb
 bne 25b
 puls d restore registers
 tfr d,x put buffer addr in X
 lda #DMFPSDC Send Device Characteristics
 jsr cpb_cmd send command to DMFP-58
 if 0
 jsr prt_env print everything of interest
 endif
 ldx 2,s restore drive index
 inc devdc,x mark "device characteristics sent"
99 puls d,x,y,u,pc return
 if 0
*
* prt_dct - print device characteristics table
*   Y - table address
*
prt_dct pshs d,x,y,u
 ldx #00f
 jsr Pdata
 leax 0,y
 leay 11,x
 jsr DumpXY
 puls d,x,y,u,pc
00 fcc $d,'Set Winchester DCT:',0
 endif
*
* setdm - Update the DMFP-58 Drive Map
*    jsr setdm
*
setdm pshs d,x,y,u save registers
 lda opncnt get # devices open
 deca
 sta fp_drive set in CPB
 ldx #drvmap compute drive map
 clra
10 ldy #devlun find drive (A) in tables
 clrb
15 cmpa ,y++ (carefull!)
 beq 20f
 incb
 cmpy #devlun+(8*2)
 bne 15b
 ldb #$FF
20 stb ,x+ place in map
 inca
 cmpa #4
 bne 10b
 ldx #drvmap compute addr of drive map
 lda #DMFPSDM set Drive Map command
 jsr cpb_cmd
99 puls d,x,y,u,pc return
*
* cpb_cmd - Send command to DMFP-58 and wait for response
*    (A) - Command to send
*    (X) - Buffer to send
*
cpb_cmd pshs d,x,y save registers
 ldy #fp_data copy buffer into good space
 ldb #32 copy 32 bytes
05 lda ,x+
 sta ,y+
 decb
 bne 05b
 ldd #fp_data get buffer address
 jsr MapLA turn logical addr into physical one
 sta fp_maddr
 sty fp_maddr+1
 bsr cpb_idle make sure controller is ready
 lda 0,s restore command
 ora #$20 Send with no interrupt
 sta fp_cmd
 jsr cpb_idle wait for idle
 puls d,x,y,pc return
*
* cpb_idle - wait for DMFP-58 to go idle
*
cpb_idle
10 mul ** Idle **
 mul
 lda fp_cmd
 anda #%11100000 get handshake bits
 bne 10b wait for idle
 rts return when idle
*
* fire up DMFP operation to initiate transfer
*
dmfpio stx BDtable
 ldb bfdvn+1,y get drive #
 lbsr dmfpdvn select drive
 lbsr dmfpsdc set drive characteristics if needed
 lda bfblch,y check block number range
 cmpa #$0f
 lbhi dmfper if too big - error
*
* decide whether we are doing a read or write (or swap)
*
 ldd bfxfc,y get transfer count
 cmpd #16 special value for swap?
 lble dmfpswp
 ldb bfflag,y get buffer flags
 bitb #BFRWF are we reading?
 beq dmfpwrt go do write
 lda #DMFPRDS set Read Sector Command
 bra dmfprw go perform I/O
*
* set up for write command
*
dmfpwrt bitb #BFSPC special i/o
 beq dmfpwr9 jump if write
 ldd bfxfc,y get transfer count
 cmpd #512 is it regular block transfer?
 beq dmfpwr9 yes - normal write
 cmpd #256 FLEX write sector?
 beq dmfpwr9 yes - jump
 cmpd #DMFP_FT special count for Format Track command
 lbne dmfper bad I/O
 lda devtyp,x get drive type code
 anda #$01 floppy density indicator
 sta fp_den
 lda #DMFPFTK set Format Track command
 bra dmfprw go do operation
dmfpwr9 lda #DMFPWRS set Write Sector
dmfprw sta DMFPcmd set up command
dmfprw0 ldb bfblch,y set up block #
 stb fp_addr
 ldd bfblck,y
 std fp_addr+1
 ldb bfxadr,y set up DMA address
 stb fp_maddr
 ldd bfadr,y
 std fp_maddr+1
 if 0
 pshs d,x
 ldx #00f
 jsr Pdata
 lda bfflag,y
 jsr Phex
 ldx #01f
 jsr Pdata
 lda bfblch,y
 jsr Phex
 lda bfblck,y
 jsr Phex
 lda bfblck+1,y
 jsr Phex
 ldx #02f
 jsr Pdata
 lda bfxadr,y
 jsr Phex
 lda bfadr,y
 jsr Phex
 lda bfadr+1,y
 jsr Phex
 ldx #10f
 jsr Pdata
 lda DMFPcmd
 jsr Phex
 ldx #11f
 jsr Pdata
 lda fp_drive
 jsr Phex
99 puls d,x
 endif
dmfprwx jsr cpb_idle make sure DMFP-58 is idle
 lda DMFPcmd get command
 ora #$40 start command with interrupt on completion
 sta fp_cmd
 inc dmfpdt+dtbusy mark device busy
 rts
 if 0
00 fcc $d,'DMFP I/O - Flags: ',0
01 fcc ', Block: ',0
02 fcc ', Addr: ',0
10 fcc ', Cmd: ',0
11 fcc ', LUN: ',0
 endif
 if 0
*
* fmt_trk - Set up for Format Track
*
*-- Get device attributes
fmt_trk
 pshs x,y save device index
 cmpx #3*2 floppy or hard disk?
 bls 05f jump for floppy
 lda #0 density
 sta fp_data+9
 lda #5 6 heads
 sta fp_data+8
 bra 09f go do it to it
05 jsr cpb_idle wait for interface idle
 ldd #fp_data space for device characteristics
 jsr MapLA
 sta fp_maddr
 sty fp_maddr+1
 lda #DMFPGDC get device characteristics
 ora #$20 no interrupt
 sta fp_cmd
 jsr cpb_idle wait for command to complete
09 lda fp_data+9 get density
 bne 10f
 lda fp_data+10 single density
 bra 15f
10 lda fp_data+11 double density
15 pshs a save # sectors / track
 ldb fp_data+8 number of heads
 incb
 mul calculate sectors/cylinder
 std _r1
 ldy 3,s restore buffer header
 clra
 ldb bfblch,y
 std _r0
 ldd bfblck,y
 std _r0+2
 jsr ldiv calculate cylinder/sector
 ldd _r0+2 get cylinder #
 std fp_addr
 ldd _work get sector*head
 std _r0+2
 ldd #0
 std _r0
 clra
 puls b restore # sectors / track
 std _r1
 jsr ldiv
 lda _r0+3 get head #
 sta fp_addr+2
 lda fp_data+9 get density
 sta fp_den
 ldy 2,s restore buffer pointer
 lda bfxadr,y get buffer address
 sta fp_maddr
 ldd bfadr,y
 std fp_maddr+1
 lda #DMFPFTK Format Track Command
 sta DMFPcmd
 if 0
 ldx #01f
 jsr Pdata
 lda bfblch,y
 jsr Phex
 lda bfblck,y
 jsr Phex
 lda bfblck+1,y
 jsr Phex
 ldx #02f
 jsr Pdata
 ldx #fp_cmd
 leay 15,x
 jsr DumpXY
 endif
 puls x,y
 jmp dmfprwx go start format operation
 if 0
00 fcc $d,'Format Track - Set up',0
01 fcc $d,'DMFP Format Track - Block: ',0
02 fcc $d,'CPB:',0
 endif
 endif
*
* take care of DMFP swap request
*
dmfpswp
 lda #4 set SWAP activity code
 sta dmfpdt+dtbusy
 ldd bfadr,y get swap table pointer
 std dmfpswpt
 lda bfflag,y check direction
 bita #BFRWF Read/Write?
 beq dmfpsw0 jump for Write
 lda #DMFPRPG set Read Page opcode
 bra dmfpsw1
dmfpsw0 lda #DMFPWPG Write Page opcode
dmfpsw1 sta DMFPcmd save command
 ldb bfblch,y
 stb fp_addr
 ldd bfblck,y
 std fp_addr+1
 bra dmfpsc1 go do operation
*
* dmfpsc - Continue SWAP request
*
dmfpsc0 ldd fp_addr+1 update block address
 addd #8
 std fp_addr+1
 bcc dmfpsc1
 inc fp_addr
*
*  set up and send SWAP command
*
dmfpsc1
 ldx dmfpswpt pick up SWAP table pointer
 lda ,x+ get descriptor for next segment
 stx dmfpswpt save new pointer
 cmpa #DSKTRM end of list?
 lbeq dmfpin4 yes - end of operation
 cmpa #WHTHOL ** Special check for white hole **
 beq dmfpsc0 ignore all white hole transfers
 coma
 anda #$3F strip high bits
 pshs a compute physical address
 lsra
 lsra
 lsra
 lsra
 sta fp_maddr Set up DMA address
 puls a
 asla
 asla
 asla
 asla
 clrb
 std fp_maddr+1
 if 0
 pshs d,x,y
 ldx #00f
 jsr Pdata
 ldx #fp_cmd
 leay 15,x
 jsr DumpXY
 bra 99f
00 fcc $d,'DMFP Swap - CPB:',0
99 puls d,x,y
  endif
 jsr cpb_idle wait for DMFP-58 free
 lda DMFPcmd get command to send
 ora #$40 start command with interrupt
 sta fp_cmd
 rts all done
*
*  Interrupt handler for DMFP-58 Disk Controller
*
dmfpint
 lda fp_cmd aknowledge interrupt
 anda #%00011111 strip handshake bits
 ora #%11100000 set acknowledge interrupt code
 sta fp_cmd
 jsr cpb_idle wait for controller idle
 ldy dmfpdt+dtqfl get first transaction
 beq 99f jump if no transaction
 lda bfdvn+1,y check for DMFP transaction
 cmpa #DMFPminor
 blo 99f
 cmpa #DMFPminor+7
 bhi 99f
 ldd fp_status check for errors
 bne dmfper
 lda dmfpdt+dtbusy check for SWAP in progress
 beq 99f exit if no operation actually in progress
 cmpa #4
 lbeq dmfpsc0 continue SWAP
dmfpin4 clr dmfpdt+dtbusy set not busy
 clr fp_den clean up density indicator
 ldx BDtable restore Block Device Table address
 ldy dmfpdt+dtqfl pick up buffer address
 jmp BDioend end of operation
*
99 rts *** Spontaneous interrupt ***

*
* error routine - give up forever
*
dmfper0 leas 2,s clean up stack
dmfper lda bfflag,y get buffer flag
 ora #BFERR indicate failure
 sta bfflag,y stuff back in el flago
 clr dmfpdt+dtbusy clear status
 bsr prt_env print everything
 clr fp_status clear CPB status & error indicators
 clr fp_error
 bra dmfpin4
prt_env pshs d,x,y
 ldx #00f
 jsr Pdata
 ldx #fp_cmd
 leay 15,x
 jsr DumpXY
 ldx #01f
 jsr Pdata
 ldx #drvmap
 leay 15,x
 jsr DumpXY
 ldx #02f
 jsr Pdata
 ldx #dctabs
 leay (32*4)-1,x
 jsr DumpXY
 puls d,x,y,pc
00 fcc $d,'DMFP-58 - CPB:',0
01 fcc 'Current Drive Map:',0
02 fcc 'Drive Characteristic Tables:',0
 sttl DMFP-58 Character Drivers
 pag

*
* Character drivers for dmfp hard disk.
*

*
* open
*

dmfpcop
 cmpb #DMFPminor+7 check for legal drive #
 bhi dmfpcop9 jump on error
 subb #DMFPminor compute relative drive #
 lslb ** FDB tables! **
 clra
 tfr d,x
 tst devopn,x check open status
 bne dmfpcop2
 clr devtyp,x assume FD_SS
 lda #8 force known characteristics for winchester
 jsr cpydct
 clr devdc,x force device characteristics to be sent
 lda opncnt get count of open devices
 cmpa #MAXDEV too many open?
 bge dmfpcop8 yes - error
 inc opncnt update count of open devices
 jsr getlun allocate a logical unit for drive
 jsr setdm go update drive map
dmfpcop2 inc devopn,x bump open count
 rts
dmfpcop8 lda #EDFUL too many open devices
 sta uerror
 rts
dmfpcop9 lda #EBARG bad argument
 sta uerror
 rts


*
* close
*
dmfpccl jmp dmfpclose same as block

*
*  ttyset/ttyget entry
*    ttyget - return most recent device status
*    ttyset - set drive characteristics
*
dmfpcsp cmpx #0 ttyget?
 beq dmfpcsp4 no - do ttyset
dmfpcsp0
** ldy #dmfpesw
 lda #6
dmfpcsp1 ldb ,y+ pick up characters
 stb ,x+
 deca done?
 bne dmfpcsp1
 rts
dmfpcsp4 lbsr dmfpdvn compute drive #
 pshs x save device table index
 cmpx #3*2 Floppy or Hard Disk?
 bhi 10f jump for Hard disk
 lda usarg0 get # sides
 anda #$01
 lsla *2
 adda usarg0+1 get density
 sta devtyp,x set in table
 bra 25f
10 ldd usarg0 which form of set?
 cmpd #$FF00 new form starts with this value!
 bne 15f jump if old form
 ldy devdct,x point at device characteristics buffer
 lda #11 copy device table
 ldx usarg2 get table address
10 pshs y,a save registers
 jsr gtubyt get next byte
 puls a,y
 stb ,y+ place in table
 leax 1,x bump source pointer
 deca done?
 bne 10b
 bra 25f exit
15 lda usarg0+1 get model select
 cmpa #MAXDCT legal index
 bls 20f
 lda #8 no - use ST-506
20 jsr cpydct go copy table
25 puls x restore device tables index
 clr devdc,x force device characteristics to be sent
 rts

*
* read
*

dmfpcrd pshs d save device number
 jsr fchgb get buffer header
 puls d reset dev number
 bsr dmfpcn go configure header
 tst uerror any errors?
 beq dmfpcrd4
 rts error return
dmfpcrd4 pshs a save task info
 orb #BFRWF set read mode
 stb bfflag,y save in buffer
 bra dmfpcio go do it

*
* write
*

dmfpcwr pshs d save device number
 jsr fchgb get buffer header
 puls d
 bsr dmfpcn configure buffer
 tst uerror any errors?
 beq dmfpcwr4
 rts error return
dmfpcwr4 pshs a save task status

*
* do character io
*

dmfpcio jmp fchio same as floppies

*
* configure dmfp character header
*

dmfpcn std bfdvn,y set up device number
 ldd uicnt get transfer count
 std bfxfc,y set in header
 cmpd #512 is it valid?
 beq dmfpcn0
 cmpd #256 special count for FLEX disk
 beq dmfpcn0
 cmpd #DMFP_FT special counts for Format
 bne dmfpcn8
dmfpcn0 lda bfflag,y get flags
 ora #BFSPC set special bit for drivers
 sta bfflag,y save new flags
dmfpcn4 ldd uipos2 get file position
 std bfblck,y save as block number
 lda uipos+1 store upper part
 sta bfblch,y
 ldd uistrt get start address of xfr
 std bfadr,y save in header
 jsr mapupg find user page
 std bfxadr,y save in header
 ldx utask point to task entry
 lda tsmode,x get mode bits
 pshs a save
 ora #TLOCK set lock bit (keep in mem)
 sta tsmode,x save new mode
 ldb bfflag,y get flags
 puls a,pc return
dmfpcn8 lda #EBARG set error
 sta uerror
 rts return

dmfpcerr lda #EIO set error
 sta uerror
 rts return
 pag

*
* fchio
*
* Perform the io specified by the buffer header
* pointed at by Y.  ** This routine assumes the
* floppy disks are major device 0 for the block
* type drivers **
*

fchio pshs y save buffer
 ldx #blktab
 jsr [blkio,x] call block io routine
 ldy 0,s reset buffer
 jsr fnshio finish io
 jsr wakbuf awakeb buffer sleepers
 puls y reset ptr
 lda bfflag,y get flags
 anda #!(BFALOC|BFREQ|BFSPC)&$ff clear out busy bits
 sta bfflag,y save new flags
 puls a get task modes
 ldx utask get task entry location
 sta tsmode,x save task modes
 ldd #0 reset data count to 0
 std uicnt
fchio6 rts return


*
* fchgb
*
* Get the character buffer header.  If it is busy,
* sleep on it.
*

fchgb ldy #fchbuf point to header
 pshs cc save status
 seti
 lda bfflag,y get buffer flags
 bita #BFALOC is buffer busy?
 beq fchgb2
 ora #BFREQ set request buffer bit
 sta bfflag,y
 puls cc reset status
 ldb #BUFPR set priority
 jsr sleep go sleep for buffer
 bra fchgb repeat
fchgb2 lda #BFALOC set busy status
 sta bfflag,y
 puls cc,pc return
 if 0
*
* Long divide
*  Divide (_r0 -> r0+3) by (_r1 -> r1+1)
*
ldiv ldb #33 set loop counter
 pshs b save counter
 if 0
 pshs d,x
 ldx #00f
 jsr Pdata
 lda _r0
 jsr Phex
 lda _r0+1
 jsr Phex
 lda _r0+2
 jsr Phex
 lda _r0+3
 jsr Phex
 ldx #01f
 jsr Pdata
 lda _r1
 jsr Phex
 lda _r1+1
 jsr Phex
 puls d,x
 endif
 ldd #0 do init
 std _work
 bra ldiv2
ldiv1 ldd _work do subtraction
 subd _r1
 bcs ldiv2 _work > _r1 ?
 std _work set new work value
ldiv2 rol _r0+3 do shifting
 rol _r0+2
 rol _r0+1
 rol _r0
 rol _work+1
 rol _work
 dec 0,s dec the loop count
 bne ldiv1
 com _r0 compliment the result
 com _r0+1
 com _r0+2
 com _r0+3
 lsr _work adjust the remainder
 ror _work+1
 if 0
 pshs d,x
 ldx #02f
 jsr Pdata
 lda _r0
 jsr Phex
 lda _r0+1
 jsr Phex
 lda _r0+2
 jsr Phex
 lda _r0+3
 jsr Phex
 ldx #03f
 jsr Pdata
 lda _work
 jsr Phex
 lda _work+1
 jsr Phex
 puls d,x
 endif
 puls b,pc return
 if 0
00 fcc $d,'$',0
01 fcc ' / $',0
02 fcc ' = $',0
03 fcc '.',0
 endif
_r0 rzb 4
_r1 rzb 2
_work rzb 2
 endif
