Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/ergbios.s
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

361 lines
7.6 KiB
ArmAsm

*****************************************************************
* *
* CP/M-68K BIOS *
* Basic Input/Output Subsystem *
* For ERG 68000 with Tarbell floppy disk controller *
* *
*****************************************************************
.globl _init * bios initialization entry point
.globl _ccp * ccp entry point
_init: move.l #traphndl,$8c * set up trap #3 handler
clr.l d0 * log on disk A, user 0
rts
traphndl:
cmpi #nfuncs,d0
bcc trapng
lsl #2,d0 * multiply bios function by 4
movea.l 6(pc,d0),a0 * get handler address
jsr (a0) * call handler
trapng:
rte
biosbase:
.dc.l _init
.dc.l wboot
.dc.l constat
.dc.l conin
.dc.l conout
.dc.l lstout
.dc.l pun
.dc.l rdr
.dc.l home
.dc.l seldsk
.dc.l settrk
.dc.l setsec
.dc.l setdma
.dc.l read
.dc.l write
.dc.l listst
.dc.l sectran
.dc.l setdma
.dc.l getseg
.dc.l getiob
.dc.l setiob
.dc.l flush
.dc.l setexc
nfuncs=(*-biosbase)/4
wboot: jmp _ccp
constat: move.b $ffff01,d0 * get status byte
andi.w #2,d0 * data available bit on?
beq noton * branch if not
moveq.l #$1,d0 * set result to true
rts
noton: clr.l d0 * set result to false
rts
conin: bsr constat * see if key pressed
tst d0
beq conin * wait until key pressed
move.b $ffff00,d0 * get key
and.l #$7f,d0 * clear all but low 7 bits
cmpi.b #1,d0
beq break
rts
break:
trap $f
.dc.w 0 * return to MACSBUG
rts
conout: move.b $ffff01,d0 * get status
and.b #$1,d0 * check for transmitter buffer empty
beq conout * wait until our port has aged...
move.b d1,$ffff00 * and output it
rts * and exit
lstout: rts
pun: rts
rdr: rts
listst: move.b #$ff,d0
rts
*
* Disk Handlers for Tarbell 1793 floppy disk controller
*
maxdsk = 2 * this BIOS supports 2 floppy drives
dphlen = 26 * length of disk parameter header
iobase = $00fffff8 * Tarbell floppy disk port base address
dcmd = iobase * output port for command
dstat = iobase * input status port
dtrk = iobase+1 * disk track port
dsect = iobase+2 * disk sector port
ddata = iobase+3 * disk data port
dwait = iobase+4 * input port to wait for op finished
dcntrl = iobase+4 * output control port for drive selection
home: clr.b track
rts
seldsk:
* select disk given by register d1.b
moveq #0,d0
cmp.b #maxdsk,d1 * valid drive number?
bpl selrtn * if no, return 0 in d0
move.b d1,seldrv * else, save drive number
lsl.b #4,d1
move.b d1,selcode * select code is 00 for drv 0, $10 for drv 1
move.b seldrv,d0
mulu #dphlen,d0
add.l #dph0,d0 * point d0 at correct dph
selrtn: rts
settrk: move.b d1,track
rts
setsec: move.b d1,sector
rts
sectran:
* translate sector in d1 with translate table pointed to by d2
* result in d0
movea.l d2,a0
ext.l d1
move.b #0(a0,d1),d0
ext.l d0
rts
setdma:
move.l d1,dma
rts
read:
* Read one sector from requested disk, track, sector to dma address
* Retry if necessary, return in d0 00 if ok, else non-zero
move.b #10,errcnt * set up retry counter
rretry:
bsr setup
ori #$88,d3 * OR read command with head load bit
move.b d3,dcmd * output it to FDC
rloop: btst #7,dwait
beq rdone * if end of read, exit
move.b ddata,(a0)+ * else, move next byte of data
bra rloop
rdone:
bsr rstatus * get FDC status
bne rerror
clr.l d0
rts
rerror: bsr errchk * go to error handler
subq.b #1,errcnt
bne rretry
move.l #$ffffffff,d0
rts
write:
* Write one sector to requested disk, track, sector from dma address
* Retry if necessary, return in d0 00 if ok, else non-zero
move.b #10,errcnt * set up retry counter
wretry:
bsr setup
ori #$a8,d3 * OR write command with head load bit
move.b d3,dcmd * output it to FDC
wloop: btst #7,dwait
beq wdone * if end of read, exit
move.b (a0)+,ddata * else, move next byte of data
bra wloop
wdone:
bsr rstatus * get FDC status
bne werror
clr.l d0
rts
werror: bsr errchk * go to error handler
subq.b #1,errcnt
bne wretry
move.l #$ffffffff,d0
rts
setup:
* common read and write setup code
* select disk, set track, set sector were all deferred until now
move.b #$d0,dcmd * clear controller, get status
move.b curdrv,d3
cmp.b seldrv,d3
bne newdrive * if drive not selected, do it
move.b track,d3
cmp.b oldtrk,d3
bne newtrk * if not on right track, do it
clr.l d3 * if head already loaded, no head load delay
btst #5,dstat * if head unloaded, treat as new disk
bne sexit
newdrive:
move.b selcode,dcntrl * select the drive
move.b seldrv,curdrv
newtrk:
bsr chkseek * seek to correct track if required
moveq #4,d3 * force head load delay
sexit:
move.b sector,dsect * set up sector number
move.b track,dtrk * set up track number
move.l dma,a0 * dma address to a0
rts
errchk:
btst.b #4,d7
bne chkseek * if record not found error, reseek
rts
chkseek:
* check for correct track, seek if necessary
bsr readid * find out what track we're on
beq chks1 * if read id ok, skip restore code
restore:
* home the drive and reseek to correct track
move.b #$0B,dcmd * restore command to command port
rstwait:
btst #7,dwait
bne rstwait * loop until restore completed
btst #2,dstat
beq restore * if not at track 0, try again
clr.l d3 * track number returned in d3 from readid
chks1:
move.b d3,dtrk * update track register in FDC
move.b track,oldtrk * update oldtrk
cmp.b track,d3 * are we at right track?
beq chkdone * if yes, exit
move.b track,ddata * else, put desired track in data reg of FDC
move.b #$18,dcmd * and issue a seek command
chks2: btst #7,dwait
bne chks2 * loop until seek complete
move.b dstat,d3 * read status to clear FDC
chkdone:
rts
readid:
* read track id, return track number in d3
move.b #$c4,dcmd * issue read id command
move.b dwait,d7 * wait for intrq
move.b ddata,d3 * track byte to d3
rid2:
btst #7,dwait
beq rstatus * wait for intrq
move.b ddata,d7 * read another byte
bra rid2 * and loop
rstatus:
move.b dstat,d7
andi.b #$9d,d7 * set condition codes
rts
flush:
clr.l d0 * return successful
rts
getseg:
move.l #memrgn,d0 * return address of mem region table
rts
getiob:
rts
setiob:
rts
setexc:
andi.l #$ff,d1 * do only for exceptions 0 - 255
cmpi #47,d1
beq noset * this BIOS doesn't set Trap 15
cmpi #9,d1 * or Trace
beq noset
lsl #2,d1 * multiply exception nmbr by 4
movea.l d1,a0
move.l (a0),d0 * return old vector value
move.l d2,(a0) * insert new vector
noset: rts
.data
seldrv: .dc.b $ff * drive requested by seldsk
curdrv: .dc.b $ff * currently selected drive
track: .dc.b 0 * track requested by settrk
oldtrk: .dc.b 0 * track we were on
sector: .dc.w 0
dma: .dc.l 0
selcode: .dc.b 0 * drive select code
errcnt: .dc.b 10 * retry counter
memrgn: .dc.w 1 * 1 memory region
.dc.l $800 * starts at 800 hex
.dc.l $17800 * goes until 18000 hex
* disk parameter headers
dph0: .dc.l xlt
.dc.w 0 * dummy
.dc.w 0
.dc.w 0
.dc.l dirbuf * ptr to directory buffer
.dc.l dpb * ptr to disk parameter block
.dc.l ckv0 * ptr to check vector
.dc.l alv0 * ptr to allocation vector
dph1: .dc.l xlt
.dc.w 0 * dummy
.dc.w 0
.dc.w 0
.dc.l dirbuf * ptr to directory buffer
.dc.l dpb * ptr to disk parameter block
.dc.l ckv1 * ptr to check vector
.dc.l alv1 * ptr to allocation vector
* disk parameter block
dpb: .dc.w 26 * sectors per track
.dc.b 3 * block shift
.dc.b 7 * block mask
.dc.b 0 * extent mask
.dc.b 0 * dummy fill
.dc.w 242 * disk size
.dc.w 63 * 64 directory entries
.dc.w $c000 * directory mask
.dc.w 16 * directory check size
.dc.w 2 * track offset
* sector translate table
xlt: .dc.b 1, 7,13,19
.dc.b 25, 5,11,17
.dc.b 23, 3, 9,15
.dc.b 21, 2, 8,14
.dc.b 20,26, 6,12
.dc.b 18,24, 4,10
.dc.b 16,22
.bss
dirbuf: .ds.b 128 * directory buffer
ckv0: .ds.b 16 * check vector
ckv1: .ds.b 16
alv0: .ds.b 32 * allocation vector
alv1: .ds.b 32
.end