mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-24 00:44:23 +00:00
361 lines
7.6 KiB
ArmAsm
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
|