; CP/M BIOS for avrcpm
; Copyright (C) 2010 Sprite_tm
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see .
;
; $Id$
;
msize: equ 62 ;size of available RAM in k
bias: equ (msize-20) * 1024
ccp: equ 3400h+bias ;base of cpm ccp
bdos: equ ccp+806h ;base of bdos
bios: equ ccp+1600h ;base of bios
cdisk: equ 0004h ;current disk number (0 ... 15)
iobyte: equ 0003h ;intel iobyte
buff: equ 0080h ;default buffer address
retry: equ 3 ;max retries on disk i/o before error
cr:equ 13
lf:equ 10
READ_FUNC: equ 7
WRITE_FUNC: equ 6
BOOT_FUNC: equ 5
HOME_FUNC: equ 4
org bios
nsects: equ ($-ccp)/128 ;warm start sector count
jp boot
wboote:
jp wboot
jp const
jp conin
jp conout
jp list
jp punch
jp reader
jp home
jp seldsk
jp settrk
jp setsec
jp setdma
jp read
jp write
jp listst
jp sectran
signon:
db cr,lf
db msize/10+'0'
db msize - (msize/10)*10 + '0' ;modulo doesn't work?
db "k cp/m vers 2.2"
msgnl: db cr,lf,0
const:
in a,(0)
ret
conin:
in a,(0)
cp 0ffh
jp nz,conin
in a,(1)
ret
conout:
ld a,c
out (2),a
ret
list:
ret
listst:
ld a,0
ret
punch:
ret
reader:
ld a,01Fh
ret
prmsg:
ld a,(hl)
or a
ret z
push hl
ld c,a
call conout
pop hl
inc hl
jp prmsg
prhex:
ld a,c
push af
rra
rra
rra
rra
call prhexdigit
pop af
; fall thru
prhexdigit:
and 00fh
cp 10
jp c,prd1
add a,7
prd1:
add a,'0'
ld c,a
jp conout
boot:
ld sp,buff
ld hl,signon
call prmsg
xor a
ld (bootdsk),a
ld a,(dpb)
ld (bootspt),a
ld c,'I'-'A'
call seldsk
ld a,h
or l
jp z,boot1
ld de,10
add hl,de
ld e,(hl)
inc hl
ld d,(hl) ;de = dpb of first ram disk
ld hl,7
add hl,de
ld a,(hl) ;get drm
add 3 ;ToDo: this works only up to 252 dir entries
and 0fch
rrca ;4 dir entries per sector
rrca ;Number of sectors to init
push af
ld bc,6
add hl,bc
ld c,(hl) ;Start track (= # of reserved tracks)
push bc ;Save track
; Check, if we have reserved tracks.
ld a,c
or a
jp z,boot0 ;Skip if not.
; Save CPM to ram disk.
ld a,(de) ;sectors per track
ld (bootspt),a
ld a,'I'-'A'
ld (bootdsk),a
call home
ld b,nsects
ld c,0 ;track
ld d,1 ;sektor (0 based)
ld hl,ccp
store1:
push bc
push de
push hl
ld c,d
ld b,0
call setsec
pop bc
push bc
call setdma
ld c,0
call write
pop hl
ld de,128
add hl,de
pop de
pop bc
dec b
jp z,boot0
inc d
ld a,(bootspt)
dec a
cp d ;if sector >= spt then change tracks
jp nc,store1
ld d,0
inc c
push bc
push de
push hl
ld b,0
call settrk
pop hl
pop de
pop bc
jp store1
; Clear directory area of ram disk.
boot0:
pop bc
call settrk
pop af
ld d,a ;d = # of sectors
ld e,0 ;e = sector
push de
ld hl,dirbuf ;Clear dirbuf
ld c,128
ld a,0E5h
boot_cl:
ld (hl),a
inc hl
dec c
jp nz,boot_cl
ld bc,dirbuf
call setdma
pop de
boot_cl2:
push de
ld c,e
ld b,0
call setsec
ld c,0
call write
pop de
inc e
dec d
jp nz,boot_cl2
boot1:
xor a
ld (iobyte),a
ld (cdisk),a
jp gocpm
wboot: ;re-load CP/M
ld sp,buff
ld a,1<= spt then change tracks
jp nc,load1
ld d,0
inc c
push bc
push de
push hl
ld b,0
call settrk
pop hl
pop de
pop bc
jp load1
gocpm:
ld a,0c3h
ld (0),a
ld hl,wboote
ld (1),hl
ld (5),a
ld hl,bdos
ld (6),hl
ld bc,buff
call setdma
ld a,(cdisk)
ld c,a
jp ccp
seldsk:
ld hl,dphtab
ld b,0
add hl,bc
add hl,bc
ld a,(hl) ;get table entry for selected disk
inc hl
ld h,(hl)
ld l,a
or h ;no entry, no disk
ret z ;
ld a,c
out (15),a
in a,(15) ;querry, if disk exists
or a ;0 = disk is ok
ret z
ld hl,0 ;error return code
ret
home:
ld a,1<