home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
norge.freeshell.org (192.94.73.8)
/
192.94.73.8.tar
/
192.94.73.8
/
pub
/
computers
/
cpm
/
alphatronic
/
SUPERBIOS.ZIP
/
QUAD-SBC
/
LDRDBIOS.MAC
< prev
next >
Wrap
Text File
|
1999-03-13
|
16KB
|
668 lines
.z80
include SUPRBIOS.LIB
rtrys equ 010d
;----------------------------------
; HDC-1001 REGISTER PORT ADDRESSES
; ---------------------------------
hbase equ 0e0h ; base port address of hdc-1001
hdata equ hbase+0 ; data register
herror equ hbase+1 ; error register
hwrtpre equ hbase+1 ; write pre-compensation register
hseccnt equ hbase+2 ; sector count register
hsec equ hbase+3 ; sector number register
hcyllow equ hbase+4 ; cylinder low register
hcylhi equ hbase+5 ; cylinder high register
hsdh equ hbase+6 ; size - drive - head register
hstatus equ hbase+7 ; status register port
hcmd equ hbase+7 ; command register port
;-------------------
; HDC-1001 COMMANDS
;-------------------
cmdrst equ 010h ; restore command
cmdrd equ 020h ; read sector command
;-----------------------------
; STATUS REGISTER BIT TESTERS
;-----------------------------
bsybit equ 080h ; busy bit
rdybit equ 040h ; data request bit
errbit equ 001h ; error bit
;------------------
; BIOS JUMP VECTOR
;------------------
start:
jp boot
jp wboot
jp const
jp conin
jp conout
jp list
jp punch
jp reader
jp hhome
jp hseldsk
jp hsettrk
jp hsetsec
jp setdma
jp hread
jp hwrite
jp listst
jp sectran
;-----------
; COLD BOOT
;-----------
boot:
ret
;-----------
; WARM BOOT
;-----------
wboot:
ret
;-------------
; LIST OUTPUT
;-------------
list:
ret
;--------------
; PUNCH OUTPUT
;--------------
punch:
ret
;---------------
; READER OUTPUT
;---------------
reader:
ret
;-------------
; LIST STATUS
;-------------
listst:
ret
;----------------
; CONSOLE STATUS
;----------------
const: ;poll serial in-return A=0ff if char ready, else 0
add A,A
inc A ;A=command port
ld C,A
in A,(C)
and 1
ret z ;no character waiting
ld A,0ffh
ret
;---------------
; CONSOLE INPUT
;---------------
conin:
ld B,A
call const
ld A,B
jr z,conin ;loop until character received
add A,A
ld C,A
in A,(C)
and 7fh ;mask high order bit
ret
;----------------
; CONSOLE OUTPUT
;----------------
conout::
ld B,C ;character to output
add A,A
inc A
ld C,A
serst:: in A,(C)
and 4
jr z,serst
dec C
out (C),B
ret
; miscellaneous character i/o routines
pmsg:: ;equivalent to BDOS function 9 (print)
ld A,(DE)
cp '$'
ret z
ld C,A
inc DE
push DE
xor A
call conout
pop DE
jr pmsg
phex:: ;print A in hex
push AF
rra
rra
rra
rra
call hex1
pop AF
hex1:: and 0fh
add A,90h
daa
adc A,40h
daa
ld C,A
xor A
jp conout
;------------------
; SET DMA ADDRESS
;-----------------
setdma:
ld (dmaadr),bc ; shared among all drivers
ret
;--------------------
; SECTOR TRANSLATION
;--------------------
sectran:
ld h,b
ld l,c
ret
;-------------
; SELECT DISK
;-------------
hseldsk:
ld hl,ddb0 ; get deblocking parameters
ld de,dbconst ; move dblk pars to usage area
ld bc,13d ; 13 bytes of dblk pars
ldir ; move as block
ld hl,dph0 ; ret w. dsk parameter hder in hl
ret
;------
; HOME
;------
hhome:
call restore ; restore drive heads to trk 0
ret
;-----------
; SET TRACK
;-----------
hsettrk:
ld (sektrk),bc ; bc contains selected track n.
ret
;------------
; SET SECTOR
;------------
hsetsec:
ld (seksec),bc ; bc contains selected sector no.
ret
;-------------
; READ SECTOR
;-------------
hread:
xor a ; clear accumulator
ld (rtcnt),a ; reset retry count
ld a,1 ; set operation to read
ld (oper),a ; save it for when we do xfer
call deblk ; deblock phy sec, buf adr, and blk sec
call inbuf ; check if new sector is in buf
call xfer ; transfer data out of buf into dma
ld a,(rtcnt) ; if rtcnt not zero then error
ret
;--------------
; WRITE SECTOR
;--------------
hwrite:
ret
;------------------------------------
; DEBLOCK PHY SEC, BUF ADDR, BLK SEC
;------------------------------------
deblk:
ld a,(pdrv) ; get phy drv from dsk deblk parameters
ld (sekprv),a ; save it as sek phy drv
ld a,(secshf) ; convert sek sec to phy sec
ld de,(seksec) ; secshf is log2 cpm sps
call shfr16 ; shift de-reg, a-reg times
ld a,(hstspt_1) ; de now contains sec rel to cyl
and e ; mask for sec rel to platter
ld (dsec),a ; save it as deblocked sector
ld a,(hdshf) ; convert seksec to phy head
ld de,(seksec) ; hdshf is log2 cpm spt
call shfr16 ; hd no is high bits, so no msk needed
ld a,(hdoff) ; add in head off set for partioning
add a,e ; cartriage drv must be part. by hds
ld (dhd),a ; save it as deblocked head no.
lΣ a,(cpmsps_1⌐ ╗ conver⌠ sekseπ t∩ hs⌠ buµ no.
ld de,(seksec) ; mask out low order bits of sec no
and e ; since buf no <= 8, need only lsb
ld e,a ; mul buf no x128 to get rel adr in buf
ld d,0 ; zero out high order of multiplicitan
ld a,7 ; convert hst buf no. to hst buf adr
call shfl16 ; mult by 128 (shift lf 7)
ld hl,hstbuf ; base addr of hst buf
add hl,de ; add in offset
ld (dadr),hl ; save it as deblocked buf addr
ld a,(blkshf) ; convert seksec to blk no.
ld de,(seksec) ; blkshf = log2 cpm spb, what we are
call shfr16 ; doing is, bl=int(sesc/cpmspb)
ld (dblk),de ; save as blk no. on this trk
ld a,(hstspb_1) ; convert seksec to hst sec no. in blk
ld de,(dsec) ; must use sec just deblocked
and e ; and deblk sec w. hst spb
ld (dblsec),a ; save it as deblocked block sec
ret
;----------------------------
; CHECK IF NEW SEC IS IN BUF
;----------------------------
inbuf:
ld a,(seklrv) ; check if new drv = old drv
ld hl,hstlrv ; first check if log drives are same
cp (hl) ; compare w. last accessed drv
jp nz,difblk ; if drvs are dif, then so is blk
ld de,(sektrk) ; check if new trk = old trk
ld hl,(hsttrk) ; this is the old trk
call cmp16 ; so far drv same
jp nz,difblk ; if trks are dif, then so is blk
ld a,(dhd) ; check if new head = old head
ld hl,hsthd ; so far drv, trk same
cp (hl) ; if dif hd, could be
jp nz,ckblk ; same blk if blk size > phy trk siz
ld a,(dsec) ; check if new sec = old sec
ld hl,hstsec ; this is the old sec
cp (hl) ; so far drv, trk, hd same
jp nz,ckblk ; could be same blk even if dif sec
call sethst ; everything same, set buf addr though
ret
ckblk:
ld hl,(dblk) ; check if new sec is in same blk
ld de,(hstblk) ; if the new blk equal old blk
call cmp16 ; then do not reset usage vars
jp nz,difblk ; regardless fall through to prerd
samblk:
call hflush ; sam blk, but dif blk sec so flush old
ld hl,usgblk ; check if this sec free in block
ld de,(dblsec) ; look in block usage vector
ld d,0 ; index down to correct entry in vector
add hl,de ; hl now contains addr of blk usg entry
ld b,(hl) ; get blk usage flag
ld a,(oper) ; get oper
or b ; if (sec not fre) or (oper is read)
jp nz,prerd ; then need to pre-read sector
nprerd:
call sethst ; sector not allocated
ret
difblk:
call hflush
call setusg ; sector not in block
prerd:
call sethst ; sector in blk but alloc, or dif blk
call hrdhst ; read in new setor
ret
;-------------------
; FLUSH HOST BUFFER
;-------------------
hflush:
ld a,(wrtpnd) ; check if host buffer active
and a ; wrtpnd =0 if inactive, =0ff if active
call nz,hwrthst ; physicaly flush buffer if active
xor a ; clear write pending
ld (wrtpnd),a ; host buffer now in active
ret
;---------------------------------
; SET DEBLOCKED VARS TO HOST VARS
;---------------------------------
sethst:
ld hl,sekvars+2 ; blk move sek & dblk vars to hst vars
ld de,hstvars ; dont need seksec so sekvars+2
ld bc,14d ; this is how many to move
ldir ; set host variables
ret
;--------------------------------------
; TRANSFER DATA TO/FROM BUFFER AND DMA
;--------------------------------------
xfer:
ld bc,080h ; transfer 128 bytes
ld de,(dmaadr) ; load cpm addr (dma addr storage)
ld hl,(hstadr) ; load buf addr
ld a,(oper) ; check if read or write operation
or a ; oper =0 if read, =1 if write
jp nz,transf ; jump if read
ex de,hl ; read operation so switch directions
transf:
ldir ; send 128 byte block
ret
;--------------------------------
; SET OR RESET BLOCK USAGE FLAGS
;--------------------------------
rsetusg:
ld b,0 ; set all block sectors in blk to free
jp setblk ; sec in blk not allocated if =0
setusg:
ld b,0ffh ; set all block sectors in blk to used
setblk:
ld a,(hstspb_1) ; get no of host sector per block
ld hl,usgblk ; get addr of blk sector usage vector
setflg:
ld (hl),b ; set or reset block usage flag
inc hl ; point to next flag loc
dec a ; dec count of block sectors to go
jp p,setflg ; loop if more to set
ret
;------------------------------
; UPDATE BLOCK USAGE VARIABLES
;------------------------------
update:
ld de,(blksec) ; we have just written to a sec in blk
ld d,0 ; so set block sec usage flag to used
ld hl,usgblk ; first point to flag
add hl,de ; de contains sector no. in block
ld a,0ffh ; 0ff means sector in block is not free
ld (hl),a ; set flag
ret
;------------
; WRITE HOST
;------------
hwrthst:
ret
;-----------
; READ HOST
;-----------
hrdhst:
call settsk ; first set up controller registers
ld a,cmdrd ; load a with command to read sector
out (hcmd),a ; send read command to command reg
call polbsy ; wait until not busy
call rxdta ; transfer data from cnt buf to hst buf
call retrys ; check for errors
jp nz,hrdhst ; retrys sets zero flg if no errors
ret
;---------------
; SET TASK FILE
;---------------
settsk:
ld a,(hstprv) ; get physical drive no.
ld b,a ; save in b so can use a for mem fetch
sla b ; rotate phy drive to correct position
sla b ; drive is expected in bits 3 and 4
sla b ; last shift for drive
ld a,(hstsdh) ; get sdh sect size setting
or b ; or it in w. rotated phy drive no
ld b,a ; save result in b
ld a,(hsthd) ; get host head no.
or b ; or it in w. drv and sec siz
out (hsdh),a ; send it siz drv hd register
ld bc,(hsttrk) ; host track is really host cylinder
ld a,b ; move msb to a-reg for out inst
out (hcylhi),a ; send high byte to cylhi reg
ld a,c ; move lsb to a-reg
out (hcyllow),a ; send to cyl low
ld a,(hstsec) ; get host sector no
out (hsec),a ; send to sector register
ret
;-----------
; SEND DATA
;-----------
snddta:
ret
;--------------
; RECIEVE DATA
;--------------
rxdta:
ld a,(hstsiz) ; this is how many bytes to move
ld b,a ; set up for inir
ld c,hdata ; this is where the data comes from
ld hl,hstbuf ; this is where the data goes
inir ; block move data into hst buf
ld a,(hstsiz+1) ; check if moving 512 bytes
and 2 ; msb would be 2 if 512 bytes
jp z,rxout ; jump over if moveing 128 or 256 only
inir ; b should be zero, hl and c set also
rxout:
ret
;--------------------------------
; RESTORE DRIVE HEADS TO TRK 000
;--------------------------------
restore:
ld a,(stprte) ; set step rate when doing a restore
ld b,cmdrst ; get a restore command
or b ; or in step rate
out (hcmd),a ; send it to the command register
call polbsy ; wait until not busy
ret
;-----------
; POLL BUSY
;-----------
polbsy:
in a,(hstatus) ; read status port
and a ; set flags
jp m,polbsy ; loop if busy bit set
and errbit ; mask for error bit
ret
;---------------------
; SET RETRY CONDITION
;---------------------
retrys:
in a,(hstatus) ; read status register
and errbit ; mask for error bit
jp z,rtout ; jump to exit rtry
ld a,(rtcnt) ; get no. of retrys so far
inc a ; increment retry count
ld (rtcnt),a ; save it for next time
cp rtrys ; set not z flg, unless rtcnt = rtrys
ret ; return w. flag set or reset
rtout:
xor a ; clear zero flag
ld (rtcnt),a ; clear retry cnt in case had to retry
ret ; return w. no errors
;----------------
; SHIFT RIGHT 16
;----------------
shfr16:
and a ; shift de reg right a-reg times
jp z,xr16 ; jump over loop if shift 0 times
shfrlp:
srl d ; shift msb first, bit 0 into carry
rr e ; rotate carry into bit 7 lsb
dec a ; decrement shift counter
jp nz,shfrlp ; loop util finished
xr16:
ret
;---------------
; SHIFT LEFT 16
;---------------
shfl16:
and a ; shift de-reg left a-reg times
jp z,xl16 ; check for shift zero times
shfllp:
sla e ; shf lsb first, c = bit 7, bit 0 = 0
rl d ; shf msb, bit 0 = carry
dec a ; decrement shift counter
jr nz,shfllp ; loop until a-reg eq zero
xl16:
ret
;------------------------------
; COMPARE 16-BIT DE AND HL REG
;------------------------------
cmp16:
ld a,e ; compare e-reg w. l-reg
xor l ; xor will zero accum. if e = l
ret nz ; return if not equal
ld a,d ; compare d-reg w. h-reg
xor h ; set zero flag if same
ret
;------------------------------------------------
; DATA STORAGE
;------------------------------------------------
dmaadr: dw 0080h ; dma address storage
rtcnt: db 0 ; retry counter
smapadr: dw 0 ; seek drive map entry address
sekvars: ; seek variables
seksec: dw 0 ; seek sector
seklrv: db 0 ; seek logical drive
sekprv: db 0 ; seek physical drive
sektrk: dw 0 ; seek track
dhd: db 0 ; deblocked head
dsec: db 0 ; deblocked sector
dadr: dw 0 ; deblocked buffer address
dblk: dw 0 ; deblocked block no. in cylinder
dblsec: db 0 ; deblocked host sector no. in block
dbconst: ; deblocking constants (calc in ddp)
secsiz: dw 0 ; host sector size
sdhsiz: db 0 ; shd reg sector siz
pdrv: db 0 ; physical drive
hdoff: db 0 ; head offset
stprte: db 0 ; cmd reg step rate
hstspt_1: db 0 ; host sector per track
hstspb_1: db 0 ; host sectors per block
hdshf: db 0 ; log2 cpm spt
blkshf: db 0 ; log2 cpm spb
hdmsk: db 0 ; heads - 1
secshf: db 0 ; log2 cpm sps
cpmsps_1: db 0 ; cpm sps - 1
hstvars: ; host drive variables
hstlrv: db 0 ; last logical drive operated on
hstprv: db 0 ; physical drive
hsttrk: dw 0 ; track (equiv to cylinder)
hsthd: db 0 ; head
hstsec: db 0 ; sector
hstadr: dw 0 ; buffer address
hstblk: dw 0 ; block no. in current cylinder
blksec: db 0 ; host sector no. in block
hstsiz: dw 0 ; physical sector size
hstsdh: db 0 ; sdh register sector size setting
wrtpnd: db 0 ; write pending (host buffer active)
wrttyp: db 0 ; write type (0=use, 1=dir, 2=free)
oper: db 0 ; operation (0=write, 1=read)
;------------------------------------------------------------------------------
; DRIVE PARAMETER DEFINITIONS
;------------------------------------------------------------------------------
;
; dskdef < drvtyp0, drvtyp1, ... , drvtypm>
;
;------------------------------------------------------------------------------
dskdef <dma55>
endmod equ $
end
end