1 ; Various functions: init, (RAM) disk, mmc, timer
2 ; This file needs to get split up.
4 ; Copyright (C) 2010 Sprite_tm
5 ; Copyright (C) 2010 Leo C.
7 ; This file is part of avrcpm.
9 ; avrcpm is free software: you can redistribute it and/or modify it
10 ; under the terms of the GNU General Public License as published by
11 ; the Free Software Foundation, either version 3 of the License, or
12 ; (at your option) any later version.
14 ; avrcpm is distributed in the hope that it will be useful,
15 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ; GNU General Public License for more details.
19 ; You should have received a copy of the GNU General Public License
20 ; along with avrcpm. If not, see <http://www.gnu.org/licenses/>.
26 ; ------------------- DRAM Refresh Interrupt --------------------
29 ; refresh interupt; exec 2 cbr cycles
32 rjmp refrint ; tim2cmpa
38 cbi P_CAS,ram_cas ;2 1| 1|
40 cbi P_RAS,ram_ras ;2 |0 1|
44 sbi P_RAS,ram_ras ;2 |0 |0
46 dram_wait DRAM_WAITSTATES-1 ; | |
48 cbi P_RAS,ram_ras ;2 |0 1|
50 sbi P_CAS,ram_cas ;2 |0 |0
52 sbi P_RAS,ram_ras ;2 1| |0
59 ;Print a unsigned lonng value to the uart
60 ; temp4:temp3:temp2:temp = value
71 clr yl ;yl = stack level
73 ultoa1: ldi z_flags, 32 ;yh = temp4:temp % 10
74 clr yh ;temp4:temp /= 10
86 cpi yh, 10 ;yh is a numeral digit '0'-'9'
90 cp temp,_0 ;Repeat until temp4:temp gets zero
97 ultoa5: cpi yl,3 ; at least 3 digits (ms)
103 ultoa6: pop temp ;Flush stacked digits
118 ;Prints temp2:temp in hex to the uart
126 ;Prints temp in hex to the uart
133 ;Prints the lower nibble
146 ;Prints the zero-terminated string following the call statement.
186 ; ---------------- Virtual peripherial interface ----------------
188 ;The hw is modelled to make writing a CPM BIOS easier.
190 ;0 - Con status. Returns 0xFF if the UART has a byte, 0 otherwise.
191 ;1 - Console input, aka UDR.
193 ;3 - "UART" status: bit 0=rx, bit 1 = tx
194 ;4 - "UART" data register, no wait
196 ;16,17 - Track select
200 ;22 - Trigger - write to read, to write a sector using the above info;
201 ; , write to allocated/dirctory/unallocated
210 ;*****************************************************
211 ;* CP/M to host disk constants *
212 ;*****************************************************
213 .equ MAXDISKS = 4 ;Max number of Disks (partitions)
214 .equ blksize = 1024 ;CP/M allocation size
215 .equ hostsize = 512 ;host disk sector size
216 ; .equ hostspt = 20 ;host disk sectors/trk
217 .equ hostblk = hostsize/128 ;CP/M sects/host buff
218 ; .equ CPMSPT = hostblk*hostspt;CP/M sectors/track
220 .equ SECMSK = hostblk-1 ;sector mask
221 .equ SECSHF = log2(hostblk) ;sector shift
223 ;*****************************************************
224 ;* BDOS constants on entry to write *
225 ;*****************************************************
226 .equ WRALL = 0 ;write to allocated
227 .equ WRDIR = 1 ;write to directory
228 .equ WRUAL = 2 ;write to unallocated
229 .equ WRTMSK= 3 ;write type mask
233 ndisks: .byte 1 ;Number of CP/M disks
235 seekdsk: .byte 1 ;seek disk number
236 seektrk: .byte 2 ;seek track number
237 seeksec: .byte 1 ;seek sector number
239 hostparttbl: .byte 8*MAXDISKS ;host partition table (start sector, sector count)
241 hostdsk: .byte 1 ;host disk number
242 hostlba: .byte 3 ;host sector number (relative to partition start)
244 unacnt: .byte 1 ;unalloc rec cnt
245 unadsk: .byte 1 ;last unalloc disk
246 unatrk: .byte 2 ;last unalloc track
247 unasec: .byte 1 ;last unalloc sector
249 erflag: .byte 1 ;error reporting
250 wrtype: .byte 1 ;write operation type
251 dmaadr: .byte 2 ;last dma address
252 hostbuf: .byte hostsize ;host buffer (from/to SD-card)
268 printstring "Debug: "
302 ;Called with port in temp2. Should return value in temp.
318 cpi temp2,TIMER_MSECS
320 cpi temp2,TIMER_MSECS+6
328 ;Called with port in temp2 and value in temp.
355 cpi temp2,TIMER_MSECS+6
366 brsh dsk_dchrd ;maybe ramdisk
368 ; Check if selected disk # is less then # of disks.
390 cpi temp,RAMDISKNR+RAMDISKCNT
394 ldi temp,0xff ;error return
440 printstring "Disk read: "
444 printstring "Disk write: "
449 printstring ": track "
453 printstring ", sector "
456 printstring ", dma-addr "
464 printstring " wrtype "
470 ;See what has to be done.
480 printstring "DISK I/O: Invalid Function code: "
485 sts ndisks,_0 ;no active partitions
487 cbi flags,hostact ;host buffer inactive
488 sts unacnt,_0 ;clear unalloc count
492 sbis flags,hostwrt ;check for pending write
493 cbi flags,hostact ;clear host active flag
499 sbi flags,readop ;read operation
508 sbi flags,rsflag ;must read data
509 ldi temp,WRUAL ;write type
510 sts wrtype,temp ;treat as unalloc
511 rjmp dsk_rwoper ;to perform the read
515 ;write the selected CP/M sector
517 cbi flags,readop ;not a read operation
527 sts wrtype,temp ;save write type
529 cpi temp,WRUAL ;write unallocated?
530 brne dsk_chkuna ;check for unalloc
532 ; write to unallocated, set parameters
533 ldi temp,blksize/128 ;next unalloc recs
535 lds temp,seekdsk ;disk to seek
536 sts unadsk,temp ;unadsk = sekdsk
538 sts unatrk,temp ;unatrk = sectrk
540 sts unatrk+1,temp ;unatrk = sectrk
542 sts unasec,temp ;unasec = seksec
545 ;check for write to unallocated sector
546 lds temp,unacnt ;any unalloc remain?
548 breq dsk_alloc ;skip if not
550 ; more unallocated records remain
551 dec temp ;unacnt = unacnt-1
553 lds temp,seekdsk ;same disk?
555 cp temp,temp2 ;seekdsk = unadsk?
556 brne dsk_alloc ;skip if not
563 cp temp,temp3 ;seektrk = unatrk?
565 brne dsk_alloc ;skip if not
567 ; tracks are the same
568 lds temp,seeksec ;same sector?
570 cp temp,temp2 ;seeksec = unasec?
571 brne dsk_alloc ;skip if not
573 ; match, move to next sector for future ref
574 inc temp2 ;unasec = unasec+1
576 cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
577 brlo dsk_noovf ;skip if no overflow
579 ; overflow to next track
580 sts unasec,_0 ;unasec = 0
583 subi temp, low(-1) ;unatrk = unatrk+1
589 cbi flags,rsflag ;rsflag = 0
590 rjmp dsk_rwoper ;to perform the write
593 ;not an unallocated record, requires pre-read
594 sts unacnt,_0 ;unacnt = 0
595 sbi flags,rsflag ;rsflag = 1
597 ;*****************************************************
598 ;* Common code for READ and WRITE follows *
599 ;*****************************************************
602 ;enter here to perform the read/write
604 printstring ", flags: "
608 sts erflag,_0 ;no errors (yet)
610 ;Convert track/sector to an LBA address (in 128byte blocks)
616 lds temp4,seektrk+1 ;
622 add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack
626 andi temp,SECMSK ;mask buffer number
627 push temp ;save for later
629 ;Convert from CP/M LBA blocks to host LBA blocks
637 ;yl:xh:xl = host block to seek
638 ; active host sector?
639 in _tmp0,flags ;host active flag
640 sbi flags,hostact ;always becomes 1
641 sbrs _tmp0,hostact ;was it already?
642 rjmp dsk_filhst ;fill host if not
644 ; host buffer active, same as seek buffer?
646 lds temp2,hostdsk ;same disk?
647 cp temp,temp2 ;seekdsk = hostdsk?
650 ; same disk, same block?
660 ;proper disk, but not correct sector
661 sbis flags,hostwrt ;host written?
666 rcall dsk_writehost ;clear host buff
672 ;may have to fill the host buffer
679 sbic flags,rsflag ;need to read?
680 rcall dsk_readhost ;yes, if 1
681 cbi flags,hostwrt ;no pending write
685 ;copy data to or from buffer
688 pop temp2 ;get buffer number (which part of hostbuf)
690 add zl,r0 ;offset in hostbuf
695 printstring "; host buf adr: "
703 ldi temp3,128 ;length of move
704 sbic flags,readop ;which way?
705 rjmp dsk_rmove ;skip if read
707 ; mark write operation
708 sbi flags,hostwrt ;hostwrt = 1
724 ; data has been moved to/from host buffer
725 lds temp,wrtype ;write type
726 cpi temp,WRDIR ;to directory?
728 ret ;no further processing
730 ; clear host buffer for directory write
736 rcall dsk_writehost ;clear host buff
737 cbi flags,hostwrt ;buffer written
740 ;*****************************************************
742 ; hostdsk = host disk #, (partition #)
743 ; hostlba = host block #, relative to partition start
744 ; Read/Write "hostsize" bytes to/from hostbuf
784 printstring ", max: "
832 ;*****************************************************
833 ;* WRITEhost performs the physical write to *
834 ;* the host disk, READhost reads the physical *
836 ;*****************************************************
841 printstring "host write "
865 printstring "host read "
892 ;***************************************************************************
896 ; ----------------- RAM disk -----------------
903 ;----------------------------------------------
920 DRAM_SETADDR xh, ~0,(1<<ram_ras), ~0,(1<<ram_a8)|(1<<ram_oe)
933 ;----------------------------------------------
942 printstring "rd-adr: "
946 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
950 dram_wait DRAM_WAITSTATES ;
957 dram_wait DRAM_WAITSTATES ;
958 in temp2,P_DQ-2 ; PIN
985 printstring "wr-adr: "
998 ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1004 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1005 ori temp,(1<<ram_cas)
1007 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1012 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1013 ori temp2,(1<<ram_cas)
1022 ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1028 #endif /* RAMDISKCNT */
1030 ;---------------------------------------------------------------------
1032 ; Partition table offsets:
1034 #define PART_START 8
1035 #define PART_SIZE 12
1045 andi temp,MMCST_NOINIT & MMCST_NODISK
1048 ;Load first sector from MMC (boot sector)
1061 ldi temp2,8*MAXDISKS
1068 ;Test, if it has a valid MBR
1070 ldiw z,hostbuf+510-1 ;Point to last byte of partition table
1072 ldi temp3,0 ;temp3 holds number of found disks (paritions)
1073 ldd temp,z+1 ;MBR signature (0xAA55) at and of sector?
1080 ;No MBR, no partition table ...
1081 inc temp3 ;pretend we have one.
1082 ldi temp,high((1<<16) * 128/512)
1083 std y+0,_0 ;start at beginning of card
1087 std y+4,_0 ;max CP/M 2.2 disk size
1093 ;Search Partition Table for CP/M partitions
1095 sbiw z,63 ;Now at first byte of partition table
1096 ldi temp4,high(hostbuf+510)
1098 ldd temp,z+PART_TYPE
1102 ; Found a CP/M partition
1104 ldd temp,z+PART_START
1106 ldd temp,z+PART_START+1
1108 ldd temp,z+PART_START+2
1110 ldd temp,z+PART_START+3
1113 ldd temp,z+PART_SIZE
1115 ldd temp,z+PART_SIZE+1
1117 ldd temp,z+PART_SIZE+2
1119 ldd temp,z+PART_SIZE+3
1127 cpi zl,low(hostbuf+510)
1133 ;Store new partitions and check if the SD card has been changed.
1137 ldi temp4,8*MAXDISKS
1161 ;---------------------------------------------------------------------
1162 ; Print partition table info
1167 ldd xl,z+4 ;Get partition size
1171 cp xl,_0 ;If zero ...
1175 breq pppre ;... No more partitions.
1177 ldd temp,z+0 ;Get partition start
1182 cp temp,_0 ;If zero ...
1186 breq prnop ;... no partition table at 0
1194 printstring ", size: "
1206 ldi temp,high(hostparttbltop)
1207 cpi zl, low (hostparttbltop)
1214 printstring "CP/M partition at: "
1217 printstring "Assuming CP/M image at: "
1220 ; ****************************************************************************
1222 ; ------------- system timer 1ms ---------------
1235 ; don't change order here, clock put/get depends on it.
1236 cntms_out: ; register for ms
1238 utime_io: ; register for uptime.
1245 .equ timer_size = timer_top - timer_base
1247 .equ clkofs = cnt_1ms-cntms_out
1248 .equ timerofs = cnt_1ms-timer_ms
1253 .org OC1Baddr ; Timer/Counter1 Compare Match B
1254 rjmp sysclockint ; 1ms system timer
1267 #if DRAM_8BIT /* Implies software uart */
1293 ldi zl,high(1000) ;doesn't change flags
1326 sts delay_timer1,temp
1328 lds temp,delay_timer1
1337 subi temp2,TIMER_MSECS
1338 brcs clkget_end ;Port number in range?
1340 breq clkget_copy ;lowest byte requestet, latch clock
1342 brsh clkget_end ;Port number to high?
1367 subi temp2,TIMERPORT
1368 brcs clkput_end ;Port number in range?
1373 cpi temp,starttimercmd
1375 cpi temp,quitTimerCmd
1377 cpi temp,printTimerCmd
1392 breq clkput_copy ;lowest byte requestet, latch clock
1394 brsh clkput_end ;Port number to high?
1439 ; put ms on stack (16 bit)
1460 ldd temp2,z+timerofs
1464 ldd temp3,z+timerofs
1469 ldd temp4,z+timerofs
1474 printstring "Timer running. Elapsed: "
1506 printstring "Uptime: "
1522 ; --------------- Debugging stuff ---------------
1523 ; Print a line with the Z80 main registers
1535 ldiw z,zflags_to_ch*2
1541 cpi temp,' ' ; Test if no flag
1544 ldi temp,' ' ; Flag not set