; $Id$
;
+.equ DSKSEL_DEBUG = 0
; ---------------- Defines for the Filesystem Interface -------
-
;*****************************************************
;* Disk-Manager constants *
;*****************************************************
- .equ dskType_None = 0
+ .equ dskType_None = 0
.equ dskType_CPM = 1
.equ dskType_FAT = 2
- .equ dskType_RAM = 3
+; .equ dskType_RAM = 3
;*****************************************************
;* CP/M to host disk constants *
;*****************************************************
- .equ MAXDISKS = 4 ;Max number of Disks (partitions)
+ .equ MAXDISKS = 8 ;Max number of Disks (partitions)
.equ PARTENTRY_SIZE = 9 ;Size of a Partitiontableentry
.equ blksize = 1024 ;CP/M allocation size
.equ hostsize = 512 ;host disk sector size
; .equ hostspt = 20 ;host disk sectors/trk
- .equ hostblk = hostsize/128 ;CP/M sects/host buff
-; .equ CPMSPT = hostblk*hostspt;CP/M sectors/track
- .equ CPMSPT = 26 ;
+ .equ hostblk = hostsize/128 ;CP/M sects/host buff
+; .equ CPMSPT = hostblk*hostspt ;CP/M sectors/track
+ .equ CPMSPT = 26 ;
.equ SECMSK = hostblk-1 ;sector mask
- .equ SECSHF = log2(hostblk) ;sector shift
+ .equ SECSHF = log2(hostblk) ;sector shift
;*****************************************************
;* BDOS constants on entry to write *
.equ WRDIR = 1 ;write to directory
.equ WRUAL = 2 ;write to unallocated
.equ WRTMSK= 3 ;write type mask
+
+ .equ READ_FUNC = 7
+ .equ WRITE_FUNC = 6
+ .equ BOOT_FUNC = 5
+ .equ HOME_FUNC = 4
+
;----------------------------------------------- Start of Data Segment
.dseg
-ndisks: .byte 1 ;Number of CP/M disks
+; The following 3 variables are copied from DRAM.
+; Don't change order.
+
+biosdrvtbl: .byte 2 ;
+biosdirbuf: .byte 2 ;
+biosenddat: .byte 2 ;
-seekdsk: .byte 1 ;seek disk number
-seektrk: .byte 2 ;seek track number
-seeksec: .byte 1 ;seek sector number
+ndisks: .byte 1 ;Number of CP/M disks
-unacnt: .byte 1 ;unalloc rec cnt
-unadsk: .byte 1 ;last unalloc disk
-unatrk: .byte 2 ;last unalloc track
-unasec: .byte 1 ;last unalloc sector
+; The following 5 variables are accessed from 8080/z80 via the
+; virtual port interface. Don't change order.
-erflag: .byte 1 ;error reporting
-wrtype: .byte 1 ;write operation type
-dmaadr: .byte 2 ;last dma address
+biospar_base:
+bcbadr: .byte 2 ;adr of BiosControlBlock
+seekdsk: .byte 1 ;seek disk number
+seektrk: .byte 2 ;seek track number
+seeksec: .byte 2 ;seek sector number
+dmaadr: .byte 2 ;last dma address
-hostbuf: .byte hostsize ;host buffer (from/to SD-card)
+unacnt: .byte 1 ;unalloc rec cnt
+unadsk: .byte 1 ;last unalloc disk
+unatrk: .byte 2 ;last unalloc track
+unasec: .byte 1 ;last unalloc sector
+
+erflag: .byte 1 ;error reporting
+wrtype: .byte 1 ;write operation type
+
+hostbuf: .byte hostsize ;host buffer (from/to SD-card)
hostparttbl: .byte PARTENTRY_SIZE*MAXDISKS ;host partition table (type, start sector, sector count)
hostparttbltop:
-hostdsk: .byte 1 ;host disk number
-hosttype: .byte 1 ;host disk type (same entry as 1 parition entry)
-hostlba: .byte 3 ;host sector number (relative to partition start)
+hostdsk: .byte 1 ;host disk number
+hosttype: .byte 1 ;host disk type (same entry as 1 parition entry)
+hostlba: .byte 3 ;host sector number (relative to partition start)
; ------------------------------- Start of Code Segment
.cseg
+;---------------------------------------------------------------------
+
+.if DSKSEL_DEBUG
+
+dbg_prdrvtbl:
+ push xh
+ push xl
+ push temp3
+ push temp2
+ push temp
+ printnewline
+ printstring "drvtbl ("
+ lds xl,biosdrvtbl
+ lds xh,biosdrvtbl+1
+ movw temp,x
+ rcall printhexw
+ printstring "): "
+ ldi temp3,16
+dbg_pcpel:
+ rcall dram_readw_pp
+ rcall printhexw
+ printstring " "
+ dec temp3
+ brne dbg_pcpel
+ pop temp
+ pop temp2
+ pop temp3
+ pop xl
+ pop xh
+ ret
+
+dbg_print_biosd:
+ printnewline
+ lds temp,bcbadr
+ lds temp2,bcbadr+1
+ rcall printhexw
+ printstring " "
+ lds temp,biosdrvtbl
+ lds temp2,biosdrvtbl+1
+ rcall printhexw
+ printstring " "
+ lds temp,biosdirbuf
+ lds temp2,biosdirbuf+1
+ rcall printhexw
+ printstring " "
+ lds temp,biosenddat
+ lds temp2,biosenddat+1
+ rcall printhexw
+ printstring " "
+ ret
+.endif
+
; ====================================================================
; Function: Get a Pointer to a Partitiontable entry
; ====================================================================
; --------------------------------------------------------------------
; Registers : [w] z Pointer to the Partitionentry
; [r] xl Number of Diskentry to Read
+; [w] _tmp0 scratch
+; [w] _tmp1 "
; --------------------------------------------------------------------
; Description:
; ====================================================================
dsk_getpartentry:
+ ldi zl,PARTENTRY_SIZE
+ mul xl,zl
ldiw z,hostparttbl
- mov temp,xl
+ add zl,_tmp0
+ add zh,_tmp1
+ ret
+
+; ====================================================================
+; Function: Virtual Port Interface
+; ====================================================================
+; Parameters
+; --------------------------------------------------------------------
+; Registers :
+; Variables :
+;
+; --------------------------------------------------------------------
+; Description:
+; ====================================================================
+
+dsk_param_getadr:
+ ldiw z,biospar_base
+ add zl,temp3
+ adc zh,_0
+ ret
+
+dsk_param_wr:
+ rcall dsk_param_getadr
+ st z,temp
+ cpi temp3,bcbadr+1-seektrk
+ brne dsk_param_wr1
+ std z+1,_0
+dsk_param_wr1:
+ cpi temp3,bcbadr+1-biospar_base
+ breq SetBCB
+ ret
+
+dsk_param_rd:
+ cpi temp3,seekdsk-biospar_base
+ breq dskDiskCheck
+ rcall dsk_param_getadr
+ ld temp,z
+ ret
+
+SetBCB:
+ lds xl,bcbadr
+ mov xh,temp
+ ldiw z,biosdrvtbl
+ ldi temp3,6
+sbcb_l:
+ rcall dram_read_pp
+ st z+,temp
+ dec temp3
+ brne sbcb_l
+
+; rcall dbg_print_biosd
+ rcall dsk_drvtblinit
+; rcall dbg_prdrvtbl
-dsk_getpartentryloop:
- cp temp,_0
- breq dsk_getpartentryloopend
- adiw z,PARTENTRY_SIZE
- dec temp
- rjmp dsk_getpartentryloop
-dsk_getpartentryloopend:
ret
; ====================================================================
-; Function:
+; Function: Check if disk exists
; ====================================================================
; Parameters
; --------------------------------------------------------------------
-; Registers : none
-; Variables : [r] seeksec Sector to read
-; [r] seektrk Track to read
+; Registers :
+; Variables :
+; return 0, if selected disk not exist.
+; return !0, if disk exist
; --------------------------------------------------------------------
; Description:
; ====================================================================
dskDiskCheck:
- lds temp2,seekdsk
- cpi temp2,RAMDISKNR
+ lds temp,ndisks
+ lds temp2,seekdsk
+.if DSKSEL_DEBUG
+ printnewline
+ printstring "DiskCheck: "
+ rcall printhexw
+.endif
+ cpi temp2,RAMDISKNR
brsh dsk_dchrd ;maybe ramdisk
; Check if selected disk # is less then # of disks.
- lds temp,ndisks
- tst temp
+ lds temp,ndisks
+ tst temp ;0 disks?
brne dsk_dchpart1
-; Need to init
+; No disks yet, need to init
- rcall mgr_init_partitions
- cbr temp,0x80
- lds temp2,seekdsk
+ rcall mgr_init_partitions ;disk chanched?
+; sbrs temp,7
+; rjmp dsk_dchpart0
+ push temp
+ rcall dsk_drvtblinit
+; rcall dbg_prdrvtbl
+ pop temp
+dsk_dchpart0:
+ cbr temp,0x80
+ lds temp2,seekdsk
dsk_dchpart1:
- cp temp2,temp
- brsh dsk_dcher
+ cp temp2,temp
+ brsh dsk_dch_err
+
+.if DSKSEL_DEBUG
+ printnewline
+ printstring "Select: "
+ mov temp,temp2
+ rcall printhex
+.endif
+ ldsw x,biosdrvtbl
+ lsl temp2 ;drive #
+ add xl,temp2
+ adc xh,_0
+ rcall dram_readw_pp ;get drive table entry
+
+ or temp,temp2 ;if !0, drive is allready initialized
+ brne dsk_dchend
+ lds temp,seekdsk
+ rcall dsk_diskinit
dsk_dchend:
- ldi temp,0
+.if DSKSEL_DEBUG
+ push temp
+ ldsw x,biosdrvtbl
+ lds temp,seekdsk
+ lsl temp ;drive #
+ add xl,temp
+ adc xh,_0
+ rcall dram_readw_pp
+ printstring ", "
+ rcall printhexw
+ pop temp
+.endif
+
ret
+dsk_dch_err:
+ ldi temp,0 ;error return
+ ret
+
+; Check RAMDISK
+
dsk_dchrd:
#if RAMDISKCNT
- cpi temp,RAMDISKNR+RAMDISKCNT
- brlo dsk_dchend
+ cpi temp,RAMDISKNR+RAMDISKCNT
+ brsh dsk_dchrd_err
+
+ ldi temp,0xff ;return ok
+ ret
#endif
-dsk_dcher:
- ldi temp,0xff ;error return
+dsk_dchrd_err:
+ ldi temp,0 ;error return
ret
-
+
+
+; ====================================================================
+; Function: Return status of last disk i/o function
+; ====================================================================
+; Parameters
+; --------------------------------------------------------------------
+; Registers :
+; Variables :
+; --------------------------------------------------------------------
+; Description:
+; ====================================================================
dskErrorRet:
- lds temp,erflag
+ lds temp,erflag
ret
-dskDiskSel:
- sts seekdsk,temp
- ret
+
+; -------------------------------------------------------------------
-dskTrackSel_l:
- sts seektrk,temp
- sts seektrk+1,_0
- ret
-dskTrackSel_h:
- sts seektrk+1,temp
+ .dseg
+tmpdpb: .byte 15
+
+ .cseg
+
+; Test DPBs (avrcpm format)
+
+dpblist:
+;dpb243
+ .db 0x1A,0x00 ;spt
+ .db 0x03,0x07 ;block shift, bock mask
+ .db 0x00,0xF2 ;extent mask, low(disk size -1),
+ .db 0x00,0x3F ;high(disk size -1), low(dir max)
+ .db 0x00,0xC0 ;high(dir max), alloc0
+ .db 0x00,0x10 ;alloc1, low(chk size)
+ .db 0x00,0x02 ;high(chk size), low(offset)
+ .db 0x00,0x00 ;high(offset), fill
+;dpb243
+ .db 0x1A,0x00 ;spt
+ .db 0x03,0x07 ;block shift, bock mask
+ .db 0x00,0xF2 ;extent mask, low(disk size -1),
+ .db 0x00,0x3F ;high(disk size -1), low(dir max)
+ .db 0x00,0xC0 ;high(dir max), alloc0
+ .db 0x00,0x10 ;alloc1, low(chk size)
+ .db 0x00,0x02 ;high(chk size), low(offset)
+ .db 0x00,0x00 ;high(offset), fill
+;dpb243
+ .db 0x1A,0x00 ;spt
+ .db 0x03,0x07 ;block shift, bock mask
+ .db 0x00,0xF2 ;extent mask, low(disk size -1),
+ .db 0x00,0x3F ;high(disk size -1), low(dir max)
+ .db 0x00,0xC0 ;high(dir max), alloc0
+ .db 0x00,0x10 ;alloc1, low(chk size)
+ .db 0x00,0x02 ;high(chk size), low(offset)
+ .db 0x00,0x00 ;high(offset), fill
+;dpb243
+ .db 0x1A,0x00 ;spt
+ .db 0x03,0x07 ;block shift, bock mask
+ .db 0x00,0xF2 ;extent mask, low(disk size -1),
+ .db 0x00,0x3F ;high(disk size -1), low(dir max)
+ .db 0x00,0xC0 ;high(dir max), alloc0
+ .db 0x00,0x10 ;alloc1, low(chk size)
+ .db 0x00,0x02 ;high(chk size), low(offset)
+ .db 0x00,0x00 ;high(offset), fill
+;dpb243
+ .db 0x1A,0x00 ;spt
+ .db 0x03,0x07 ;block shift, bock mask
+ .db 0x00,0xF2 ;extent mask, low(disk size -1),
+ .db 0x00,0x3F ;high(disk size -1), low(dir max)
+ .db 0x00,0xC0 ;high(dir max), alloc0
+ .db 0x00,0x10 ;alloc1, low(chk size)
+ .db 0x00,0x02 ;high(chk size), low(offset)
+ .db 0x00,0x00 ;high(offset), fill
+;dpb243
+ .db 0x1A,0x00 ;spt
+ .db 0x03,0x07 ;block shift, bock mask
+ .db 0x00,0xF2 ;extent mask, low(disk size -1),
+ .db 0x00,0x3F ;high(disk size -1), low(dir max)
+ .db 0x00,0xC0 ;high(dir max), alloc0
+ .db 0x00,0x10 ;alloc1, low(chk size)
+ .db 0x00,0x02 ;high(chk size), low(offset)
+ .db 0x00,0x00 ;high(offset), fill
+;dpb243
+ .db 0x1A,0x00 ;spt
+ .db 0x03,0x07 ;block shift, bock mask
+ .db 0x00,0xF2 ;extent mask, low(disk size -1),
+ .db 0x00,0x3F ;high(disk size -1), low(dir max)
+ .db 0x00,0xC0 ;high(dir max), alloc0
+ .db 0x00,0x10 ;alloc1, low(chk size)
+ .db 0x00,0x02 ;high(chk size), low(offset)
+ .db 0x00,0x00 ;high(offset), fill
+;dpb243
+ .db 0x1A,0x00 ;spt
+ .db 0x03,0x07 ;block shift, bock mask
+ .db 0x00,0xF2 ;extent mask, low(disk size -1),
+ .db 0x00,0x3F ;high(disk size -1), low(dir max)
+ .db 0x00,0xC0 ;high(dir max), alloc0
+ .db 0x00,0x10 ;alloc1, low(chk size)
+ .db 0x00,0x02 ;high(chk size), low(offset)
+ .db 0x00,0x00 ;high(offset), fill
+#if 0
+;rd1016
+ .db 0x20,0x00 ;spt
+ .db 0x04,0x0F ;block shift, bock mask
+ .db 0x00,0xFB ;extent mask, low(disk size -1),
+ .db 0x01,0xBF ;high(disk size -1), low(dir max)
+ .db 0x00,0xE0 ;high(dir max), alloc0
+ .db 0x00,0x30 ;alloc1, low(chk size)
+ .db 0x00,0x02 ;high(chk size), low(offset)
+ .db 0x00,0x00 ;high(offset), fill
+;rd9192s
+ .db 0x20,0x00 ;spt
+ .db 0x05,0x1F ;block shift, bock mask
+ .db 0x01,0xFD ;extent mask, low(disk size -1),
+ .db 0x07,0xFF ;high(disk size -1), low(dir max)
+ .db 0x01,0xF0 ;high(dir max), alloc0
+ .db 0x00,0x80 ;alloc1, low(chk size)
+ .db 0x00,0x02 ;high(chk size), low(offset)
+ .db 0x00,0x00 ;high(offset), fill
+#endif
+
+; Test
+cpy_dpb:
+ push zh
+ push zl
+ push yh
+ push yl
+ ldiw z,dpblist*2
+ ldi temp2,16
+ mul temp,temp2
+ add zl,_tmp0
+ adc zh,_tmp1
+ ldiw y,tmpdpb
+cpydpb_l:
+ lpm temp,z+
+ st y+,temp
+ cpi yl,low(tmpdpb + 15)
+ brne cpydpb_l
+ pop yl
+ pop yh
+ pop zl
+ pop zh
ret
+
+; ====================================================================
+; Function: Clear drive table
+; ====================================================================
+; Parameters
+; --------------------------------------------------------------------
+; Registers :
+; Variables :
+;
+; --------------------------------------------------------------------
+; Description:
+; ====================================================================
-dskSecSel:
- sts seeksec,temp
+; For now, only entries 1 - 7 are cleared.
+
+dsk_drvtblinit:
+ ldsw x,biosdrvtbl
+ adiw x,2
+ ldi temp3,7
+dsk_drvi_l:
+ ldi temp,0
+ ldi temp2,0
+ rcall dram_writew_pp
+ dec temp3
+ brne dsk_drvi_l
+
+ lds temp,biosenddat
+ lds temp2,biosenddat+1
+ rcall heap_init
+ clr temp
ret
-dskDmal:
- sts dmaadr,temp
+
+; ----------------------------------------------------------------------
+; Init CP/M data structures
+; temp = drive #
+;
+; return !0 if ok
+; 0 on error
+
+
+dsk_diskinit:
+ mov temp3,temp ;save disk #
+
+
+; Test
+ rcall cpy_dpb
+
+
+
+
+; get mem for DPH
+; -----------------------------------------------------------------
+; DPH: | XLT | | | |DIRBUF | DPB | CSV | ALV |
+; -----------------------------------------------------------------
+;(offset) 0 2 4 6 8 10 12 14
+
+ ldi temp, low (16)
+ ldi temp2,high(16)
+ rcall heap_get
+ brne dsk_di_1
+ rjmp dsk_di_err ;
+dsk_di_1:
+ movw x,temp
+ movw y,temp
+ ldi temp,0
+ ldi temp2,0
+ rcall dram_writew_pp ;XLT
+ adiw x,6
+ lds temp,biosdirbuf
+ lds temp2,biosdirbuf+1
+ rcall dram_writew_pp ;DIRBUF
+
+; get mem for DPB
+; -------------------------------------------------------------
+; DPB: | SPT |BSH|BLM|EXM| DSM | DRM |AL0|AL1| CKS | OFF |
+; -------------------------------------------------------------
+; 0 5 7 11 13
+
+ ldi temp, low (15)
+ ldi temp2,high(15)
+ rcall heap_get
+ breq dsk_di_err_p1
+ movw x,temp
+
+ ldiw z,tmpdpb
+dsk_dicpl:
+ ld temp,z+
+ rcall dram_write_pp
+ cpi zl,low(tmpdpb + 15)
+ brne dsk_dicpl
+ sbiw x,15
+ movw temp,x
+ movw x,y
+ adiw x,10
+ rcall dram_writew_pp ;DPB
+
+; get mem for dir check vector
+
+ lds temp,tmpdpb+11 ;cks
+ lds temp2,tmpdpb+11+1
+ cp temp,_0
+ cpc temp2,_0
+ breq dsk_dicks0
+ rcall heap_get
+ breq dsk_di_err_p1
+dsk_dicks0:
+ rcall dram_writew_pp ;CSV
+
+; get mem for alloc vector
+
+ lds temp,tmpdpb+5 ;dsm
+ lds temp2,tmpdpb+5+1
+ subi temp, low (-8)
+ sbci temp2,high(-8)
+ lsr temp2
+ ror temp
+ lsr temp2
+ ror temp
+ lsr temp2
+ ror temp ;(dsm+1+7)/8
+ rcall heap_get
+ breq dsk_di_err_p1
+ rcall dram_writew_pp ;ALV
+
+; success, insert DPH into drvtbl
+
+ lds xl,biosdrvtbl
+ lds xh,biosdrvtbl+1
+ lsl temp3 ;drive #
+ add xl,temp3
+ adc xh,_0
+ movw temp,y
+ rcall dram_writew_pp
+ ori temp,0xff ;return ok
ret
-dskDmah:
- sts dmaadr+1,temp
+; error, free mem
+
+dsk_di_err_p1:
+ movw temp,y
+ rcall heap_release
+dsk_di_err:
+ eor temp,temp ;return 0 (+ Z-flag)
ret
+
; ====================================================================
; Function: Does a Disk interaction
; ====================================================================
; Parameters
; --------------------------------------------------------------------
-; Registers : none
+; Registers : in: temp
; Variables : [r] seekdsk Number of Disk to Read
; [r] seeksec Sector to read
; [r] seektrk Track to read
dsk_read:
sts erflag,_0
sbi flags,readop ; Set read operation flag
+
+ ;RAM disk?
lds xl,seekdsk
+#if RAMDISKCNT
+ cpi xl,RAMDISKNR
+ brlt PC+2
+ rjmp rdsk_read
+#endif
rcall dsk_getpartentry ; Get Paritiontableentry
ld temp,z ; Get Partitiontype
cpi temp,dskType_None
brne PC+2
rjmp dsk_read_err
-; Is it a RamDisk ?
- cpi temp,dskType_RAM
- brne PC+2
- rjmp rdsk_read
; It must be a FAT16-Imagefile or CP/M Partition.
sts unacnt,_0
sbi flags,rsflag ;must read data
; ====================================================================
; Parameters
; --------------------------------------------------------------------
-; Registers : none
+; Registers : in: temp Write type
; Variables : [r] seekdsk Number of Disk to Read
; [r] seeksec Sector to read
; [r] seektrk Track to read
;write the selected sector
sts erflag,_0
cbi flags,readop ; not a read operation
+ ;RAM disk?
lds xl,seekdsk
+#if RAMDISKCNT
+ cpi xl,RAMDISKNR
+ brlt PC+2
+ rjmp rdsk_write
+#endif
rcall dsk_getpartentry ; Get Paritiontableentry
- ld temp,z ; Get Partitiontype
+ ld temp2,z ; Get Partitiontype
; Isn't it a Disk ?
- cpi temp,dskType_None
+ cpi temp2,dskType_None
brne PC+2
rjmp dsk_write_err
-; Is it a RamDisk ?
- cpi temp,dskType_RAM
- brne PC+2
- rjmp rdsk_write
; It must be a FAT16-Imagefile or CP/M Partition.