今回も前回に引き続きBIOSを作成していきます。そして、実際にCP/Mを起動したいと思います。

前回まだ、未完成だったwboot:から作成していきたいと思います。

wboot:では、SDCARDのシステム領域を読み取って、ccp/bdosを上書きする必要があります。 SDCARDのシステム領域はセクタ512byteのべたで保存されているので、読み込みも512byteづつ読み込みます。
cp/mのデータ領域は128byte読んで残りは捨てていますので、今回は512byteづつ連続でセクタを呼べるように読み込みルーチンread512:を作成しました。


read512: はマルチブロックリードのcmd18を使い、今回は本来の使い方であるセクタ連続読み込みを行っています。
read512_block_noをHLレジにロードします。
cmd18コマンド列の該当部分にこのHLレジスタの内容を格納します。
cmd18を発行してレスポンスを待って、1byte読み捨てしてからデータブロックの先頭の0xfeを探します。
続いて、データ256byteを2回読みしread512_addrの先頭から格納します。
データブロックの最後のcrc 2byteは読み捨てします。
これで 1ブロック(セクタ) 512byte読み終えたので、read512_blockを減算し0でなかったら再度  次のセクタ512byteの読み込み を行います。
結果が0であれば、読み取りを終了して、1byte置いてからcmd12を発行してマルチブロックリードを終了します。
cmd12のレスポンスを確認してから、データ(DI)がLレベル(ビジー)からHレベルになるまで待ちます。
正常に終了したら、Aレジスターに0x00をエラーの場合には0x01をセットして戻ります。

read512:
					;read 1sector 512byte
        ld	hl,(read512_block_no)   ;read bolck_no
					
        ld      a,(r7)
        bit     6,a
        jp      z,read512_SD_ver2
        ld      a,h                    	;SDHC
        ld      (cmd18+03),a
        ld      a,l
        ld      (cmd18+04),a
        jr      spi_read512_2
read512_SD_ver2:
        ld      a,h                    	;Ver2
        ld      (cmd18+02),a
        ld      a,l
        ld      (cmd18+03),a

spi_read512_2:
        call    dummy_data              ;dummy data(0xff) out
        ld      hl,cmd18
        call    cmd_out                 ;cmd17 Issue
        call    r1_resp
        cp      0x00                    ;response is 0x00 read mode OK?
        jr      nz,cmd18_512_err

sector_read_loop:
cmd18_512_st:
 
        call    r1_resp                 ;read data start response?
        cp      0xfe                    ;data start byte 0xfe?
        jr nz,  cmd18_512_st

 
        ld	hl,(read512_addr)       ;read data buff address
       	ld      b,0x00                  ;read data size 256byte
cmd18_512_r:
        call    resp                    ;read data
        ld      (hl),a
        inc     hl
        djnz    cmd18_512_r

        ld      b,0x00			;2st 256byte write
cmd18_512_r2st:
        call    resp
        ld      (hl),a                  ;read data
        inc     hl
        djnz    cmd18_512_r2st

        ld      (read512_addr),hl

        call    resp                    ;crc Skipping read
        call    resp                    ;crc Skipping read

	ld	hl,(read512_block)
	dec	hl
	ld	(read512_block),hl
	ld	a,h			;HL = 0?
	or	l
	jr	nz,sector_read_loop

        ld      d,0xff                  ;dummy data 0xff(cs low)
        call    spi_8bit

       	ld      hl,cmd12		;stop cmd
        call    cmd_out                 ;cmd12 Issue
	ld	d,0xff
	call	spi_8bit
        call    r1_resp
        cp      0x00                    ;response is 0x00 read mode OK?
        jr      nz,cmd18_512_err

cmd18_512_wch3:
	call	resp
	cp	0x00
	jr	z,cmd18_512_wch3

        call	set_cs		        ;CS="H"
        xor    	a
        ret

cmd18_512_err:
	call	set_cs		         ;CS="H"
	ld	a,0x01
	ret

wboot:では仮のスタックを設定してから、SDCARDのシステム領域を読み込みします。
読み込み格納するアドレスは、CCPトップの0xdc00
読み出すブロックは、最初のセクタからなので0x0000
読み出すブロック数は0x1600(CCP+BDOS)/512byteで0x000b となります。
先ほどのread512:をコールして、システム(CCP+BDOS)を0xdc00からのメモリ上に呼び出しします。
この後、gpcpm:のルーチンに続きます。

wboot:	
	ld	sp,BUFF_DEFAULT_ADDR
					;reading system block (CCP+BDS)
	ld	hl,CCP			
	ld	(read512_addr),hl	;system top addr (CCP)
	ld	hl,0x0000		
	ld	(read512_block_no),hl	;system top sector no. (512byte read)
	ld	hl,0x000b			
	ld	(read512_block),hl	;0x1600(ccp+BDOS) /512byte(sector)
	call	read512			;read system block

gocpm:				;set default buff address to 0x80
	ld	bc,BUFF_DEFAULT_ADDR
	call	setdma

	ld	a,0xc3		;jump wboot address set at 0x0000
	ld	(0x0000),a
	ld	hl,wboote
	ld	(0x0001),hl

	ld	(0x0005),a	;jump BDOS address set at 0x0005
	ld	hl,BDOS
	ld	(0x0006),hl

	ld	a,(disk_number)
	ld	c,a
	jp	cpmboot

最後の方に、BIOSのソースを展開していますが、このBIOSを基にCP/Mを起動してみたいとおもいます。
まずは、biosをアセンブルします。ソース名はbios304.asmとしています。
$ asz80 -l -s -o bios304.asm
$ aslink -i bios304

raspberryPIにUSBシリアルで接続したZ80マイコンボードにコマンドラインのシリアル端末ソフトminicomで接続します。

SDCARD(ただしSDHCタイプのみ) には前回で作成したシステムを書き込みしているとします。

minicomを起動します。

CTRL-A Z A と打ってLFを有効にします。
Z80ボードのリセットを押してモニタを再起動します。

>Monitor TMPZ84C015 CPU ver0.72(SPI) by Pinecone 2019/9/6
>
64KRAMのモニタへ移行します。 t yと打ちます。
>t Yes:

RAM area switching monitor
Monitor TMPZ84C015 CPU ver0.72(SPI) by Pinecone 2019/9/6
>
これで、RAM上のモニタになったので、まず、最初にCPM.HEXをダウンロードします。l(エル)キーを打ってモニタでHEXダウンロードの準備をします。

CTRL-A Z Y アップロードするファイルを選びます。
上下のカーソルでディレクトリ/ファイルを選び、スペースで選定します。
ここでは、cpm.hexを選定し、Enterを押してダウンロードを開始します。

続いてBIOSも同様にダウンロードします。
ここではbios304.ihxを選定し、 Enterを押してダウンロードを開始します。

先ほどのcpm.hexには旧のbiosも含まれていますので、cpm.hex、bios304.ihxの順でダウンロードを行う必要があります。

無事ダウンロードしたら、j f200 でbiosトップにジャンプします。

>j f200 y:

:SDHC

62K CP/M VERS 2.2

A>
の表示がでて、キー入力待ちになれば、成功です。
改行がCRとLFで2行改行されるので、 CTRL-A Z Aで改行を1回にします 
早速、ちゃんと動作しているか確認してみます。
まずは ディレクトリから

A>dir
A: ASM COM : DDT COM : DISKDEF LIB : DUMP COM
A: ED COM : LOAD COM : MAC COM : PIP COM
A: STAT COM : SUBMIT COM : XSUB COM : Z80 LIB
A>
ちゃんと表示されているようです。
statで詳細を見てみます。(実行までには気持ち時間が必要です)
A>stat *.*
Recs Bytes Ext Acc
64 8k 1 R/W A:ASM.COM
38 5k 1 R/W A:DDT.COM
49 7k 1 R/W A:DISKDEF.LIB
4 1k 1 R/W A:DUMP.COM
52 7k 1 R/W A:ED.COM
14 2k 1 R/W A:LOAD.COM
92 12k 1 R/W A:MAC.COM
58 8k 1 R/W A:PIP.COM
41 6k 1 R/W A:STAT.COM
10 2k 1 R/W A:SUBMIT.COM
6 1k 1 R/W A:XSUB.COM
77 10k 1 R/W A:Z80.LIB
Bytes Remaining On A: 172k
A>
Bドライブにstat.comをコピーしてみます。
A>pip b:stat.com=a:stat.com
A>dir b:
B: STAT COM
A>
コピーできたようです。
Bドライブでstatを実行してみます。
A>b:
B>stat  *.*
Recs Bytes Ext Acc
41 6k 1 R/W B:STAT.COM
Bytes Remaining On B: 235k
B>
接続されていないEドライブを指定してみます。
BDOSエラーになるので、Enterを押すとその前のドライブに戻ります。
B>e:
Bdos Err On E: Select(ここでEnterを押す)
B>

なんとか CP/Mの起動はできたみたいです。
次回はBIOSをSDCARDのシステム領域にセーブし、SDCARDのシステムを読み込んで起動できるようにしたいと思います。

以下 今回使用したBIOSのソースを展開しました。

;;z80 (TMPZ84C015) 62K cp/m V2.2 BIOS by Pinecone 2020/03/26

; TMPZ84C015 cpu
; ram 0000h -- ffffh
; External clock 20MHz

; TMPZ84C015 serial communication (CH-B)
; extemal Clock 614.4KHz(4.9152MHz TC74HC4040 1/8 Frequency division)
; Band Rate:38400  8bits 1Stopbits none Parity (81N)

; assembler
;  program start 0xF200
;  main          0xF200
;
; assemblers  ASxxxx and ASlink V5.10
; file name bios304.asm
; $ asz80 -l -s -o bios304.asm
; $ aslink -i bios304
; $ tmpz84_moni71 l command Hex load jump 0xf200


	.z80

VERS	.equ	22		;Version 2.2

MSIZE	.equ	62		;CP/M memory size 
	
BIAS	.equ	(MSIZE-20)*1024
CCP	.equ	0x3400 + BIAS	;base of cpm console processor
BDOS	.equ	0x806 +	CCP	;basic dos
BIOS	.equ	CCP + 0x1600	;BIOS
IOBYTE	.equ 	0x0003		;intel i/o byte

cpmboot	.equ	CCP

TRACK_OFFSET	.equ	2	;cp/m used tracks number

;; TMPZ84C015 serial port SIO-B CH
SIOBD	.equ	0x1A		;SIO-B CH DATA REG
SIOBC	.equ	0x1B		;SIO-B CH CONTL	REG

;; TMPZ84C015 pio port  PIO-A CH
PIOAD 		.equ 	0x1c		;PIO-A CH DATA REG
PIOAC		.equ	0x1d		;PIO-A CH CONTL	REG

;; TMPZ84C015 pio SPI OUT-PORT PIO-A CH
S_DI 		.equ 7 ;0b10000000 D7
S_CS 		.equ 6 ;0b01000000 D6
S_CLK 		.equ 5 ;0b00100000 D5

;; TMPZ84C015 pio SPI INPUT-PORT PIO-A CH
DO 		.equ 0 ;0b00000001 D0

BUFF_DEFAULT_ADDR	.equ	0x80	;default buff address
DISKS_MAX		.equ	4	;max disk
DISK_TRACK		.equ	0d0077	;1 disk>> 77 track
DISK_SECTOR		.equ	26	;1 track>> 26 sector

	.area	BIOS(ABS)

	.org	BIOS


;;	jump vector for indiviual routines
;
	jp	boot		;cold start
wboote:	jp	wboot		;warm start
	jp	const		;console status
	jp	conin		;console character in
	jp	conout		;console character out
	jp	list		;list character out
	jp	punch		;punch character out
	jp	reader		;reader character out
	jp	home		;move head to home position
	jp	seldsk		;select disk
	jp	settrk		;set track number
	jp	setsec		;set sector number
	jp	setdma		;set dma address
	jp	read		;read disk
	jp	write		;write disk
	jp	listst		;return list status
	jp	sectran		;sector translate

;;
;;     IBN-COMPATIBLE 8 Inch DISKS
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	disk Parameter header for disk 00
dpbase:	.dw	trans, 0x0000
	.dw	0x0000, 0x0000
	.dw	dirbf, dpblk
	.dw	chk00, all00
;	disk parameter header for disk 01
	.dw	trans, 0x0000
	.dw	0x0000, 0x0000
	.dw	dirbf, dpblk
	.dw	chk01, all01
;	disk parameter header for disk 02
	.dw	trans, 0x0000
	.dw	0x0000, 0x0000
	.dw	dirbf, dpblk
	.dw	chk02, all02
;	disk parameter header for disk 03
	.dw	trans, 0x0000
	.dw	0x0000, 0x0000
	.dw	dirbf, dpblk
	.dw	chk03, all03
;
;	sector translate vector
trans:	.db	 1,  7, 13, 19	;sectors  1,  2,  3,  4
	.db	25,  5, 11, 17	;sectors  5,  6,  7,  6
	.db	23,  3,  9, 15	;sectors  9, 10, 11, 12
	.db	21,  2,  8, 14	;sectors 13, 14, 15, 16
	.db	20, 26,  6, 12	;sectors 17, 18, 19, 20
	.db	18, 24,  4, 10	;sectors 21, 22, 23, 24
	.db	16, 22		;sectors 25, 26
;
dpblk:	;disk parameter block, common to all disks
	.dw	26		;sectors per track
	.db	3		;block shift factor
	.db	7		;block mask
	.db	0		;null mask
	.dw	242		;disk size-1
	.dw	63		;directory max
	.db	192		;alloc 0
	.db	0		;alloc 1
	.dw	16		;check size
	.dw	2		;track offset
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;	disk port and commands
lf	.equ	0x0a
cr	.equ	0x0d

signon:				;signon massage ??K cp/m  ?.?	
	.db	cr,lf,lf
	.db	MSIZE/10+"0",MSIZE % 10 +"0"
	.str	"K CP/M VERS "
	.db	VERS/10+"0",".",VERS % 10 +"0"
	.db	cr,lf,0

boot:
	ld	sp,BUFF_DEFAULT_ADDR + 0x80
	call	init_io
	ld	hl,signon
	call	prmsg
	xor	a
	ld	(disk_number),a
	ld	(old_disk_number),a
	ld	a,0x11
	ld	(IOBYTE),a
	jr	gocpm

wboot:	
	ld	sp,BUFF_DEFAULT_ADDR
					;reading system block (CCP+BDS)
	ld	hl,CCP			
	ld	(read512_addr),hl	;system top addr (CCP)
	ld	hl,0x0000		
	ld	(read512_block_no),hl	;system top sector no. (512byte read)
	ld	hl,0x000b			
	ld	(read512_block),hl	;0x1600(ccp+BDOS) /512byte(sector)
	call	read512			;read system block

gocpm:				;set default buff address to 0x80
	ld	bc,BUFF_DEFAULT_ADDR
	call	setdma

	ld	a,0xc3		;jump wboot address set at 0x0000
	ld	(0x0000),a
	ld	hl,wboote
	ld	(0x0001),hl

	ld	(0x0005),a	;jump BDOS address set at 0x0005
	ld	hl,BDOS
	ld	(0x0006),hl

	ld	a,(disk_number)
	ld	c,a
	jp	cpmboot

prmsg:
	ld	a,(hl)
	cp	0x00		;massage end ?
	ret	z
	ld	c,a
	call	conout
	inc	hl
	jr	prmsg

const:	in     	a,(SIOBC)
	bit	0,a
        jr      z,con_busy			;console status
	ld	a,0xff		;READY= 0xff BUSY=0x00 out Areg
	ret
con_busy:
	ld	a,0x00
	ret

reader:				;reader character out
	ld	a,0x1a
	and	0x7f
	ret

getchar:			
conin:				;console character in
	in     	a,(SIOBC)
	bit	0,a
        jr      z,getchar
	in      a,(SIOBD)
	and	0x7f
	ret		


list:				;list character out
	ld	a,c
	ret
			
punch:				;punch character out
	ld	a,c
	ret
conout:				;console character out
	ld	a,c
	call 	putchar
	ret

putchar:
	push	af
putchar01:
	in      a,(SIOBC)
        bit     2,a
        jr      z,putchar01
	pop	af
        out     (SIOBD),a
	ret
home:	
	ld	c,0x00		;track 00
	call	settrk
	ret
listst:				;return list status
	ld	a,0x00
	ret
sectran:			;sector translate
				;logical sector > BC
				;sector translate teble > de
				;return to translate ogical sector > hl
	ld	b,0
	ex	de,hl
	add	hl,bc
	ld	a,(hl)
	ld	(sector_number),a
	ld	l,a
	ret
setdma:				;set dma address set bc reg
	ld	h,b
	ld	l,c
	ld	(dma_Buff_addr),hl
	ret
seldsk:				;c reg set disk no
	ld	hl,0x0000	;err set hl=0000 return
	ld	a,c
	cp	DISKS_MAX
	jr	nc,disk_max
	ld	(disk_number),a
	ld	(old_disk_number),a
	ld	l,a
	ld	h,0x00
	add	hl,hl
	add	hl,hl
	add	hl,hl
	add	hl,hl
	ld	de,dpbase
	add	hl,de
	ret
disk_max:			
	ld	a,(old_disk_number)
	ld	(disk_number),a
	ld	hl,0x0000	;err set hl=0000 return
	ret	


settrk:				;set track address given by c
	ld	hl,track_number
	ld	(hl),c
	ret
setsec:				;set sector numbar given by c
	ld	hl,sector_number
	ld	(hl),c
	ret

init_io:			;tmpz84c015  serial siob ch/pio-a ch/spi-init
	call 	siobinit
	call	pioainit
	call    init_spi
	ret

init_spi:
        push    af
        xor     a
        set     S_CS,a          ;CS="H" 
        set     S_DI,a          ;DI="H"
        out    (PIOAD),a
        ld      b,80            ;80 clok output
        call    loopspii
        pop     af
        xor     a
        out     (PIOAD),a     ;CS="L" DI="L" CLK="L"

        call    cmd0_out
        cp      0x01
        jp      nz,init_err
        call    cmd8_out
        cp      0x01
        jp      nz,init_err
        call    cmd55_out
        cp      0x01
        jp      nz,init_err
        call    acmd41_out
        call    cmd58_out
        ld      a,(r7)
        bit     7,a
        jp      z,init_err
        bit     6,a
        jr      z,SD_ver2
        ld      hl,sdhc_msg
init_msg:
        call    msgout
	call	set_cs
        ret
SD_ver2:
        ld      hl,sd_ver2_msg
        jr      init_msg

        ret

init_err:
        ld      hl,spi_init_err_msg
        call    msgout
        ld	a,0x0d
        call	putchar
        jp      boot


cmd0_out: 
        ld      hl,cmd0
        call    cmd_out
        call    r1_resp
        ret
cmd8_out:
        call    dummy_data
        ld      hl,cmd8
        call    cmd_out
        call    r1_resp
        cp      0x01
        ret     nz
        ld      b,4
        ld      hl,r7
cmd8_r:
        call    resp
        ld      (hl),a
        inc     hl
        djnz    cmd8_r
        ld      a,0x01
        ret

cmd55_out:
        call    dummy_data
        ld      hl,cmd55
        call    cmd_out
        call    r1_resp
        ret

acmd41_out:
        call    dummy_data
        ld      hl,acmd41               ;sd-card Initialize
        call    cmd_out
        call    r1_resp
        cp      0x00
        ret     z
        call    cmd55_out
        jr      acmd41_out

cmd58_out:
        call    dummy_data
        ld      hl,cmd58
        call    cmd_out
        call    r1_resp
        push    af
        ld      b,4
        ld      hl,r7
cmd58_r:
        call    resp
        ld      (hl),a
        inc     hl
        djnz    cmd58_r
cmd58_r_d:
        ld      hl,r7
        ld      b,4
cmd58_r_d_loop:
        inc     hl
        djnz    cmd58_r_d_loop
        ld      a,0x0d
        call    putchar
        pop     af
        ret
r1_resp:
        call    resp
        cp      0xff
        jr      z,r1_resp
        ret

resp:
        ld      d,0xff  
        call    spi_8bit
        ld      a,e
        ret

cmd_out:                        ;command out
        push    hl
        push    bc
        ld      b,0x06          ;command line word count
cmd_out1:
        ld      d,(hl)          ;command line area
        call    spi_8bit
        inc     hl
        djnz    cmd_out1
        pop     bc
        pop     hl
        ret
spi_8bit:                       ;outdata Dreg,inputdata Ereg
        push    bc
        ld      c,0x00
        ld      b,0x08        
loopspi:
        xor     a
        rlc     d
        rra
        res     S_CLK,a         ;CLK    L
        out    (PIOAD),a
        nop
        nop
        nop
        nop
        nop
        nop
        set     S_CLK,a         ;CLK    H
        out    (PIOAD),a
        in     a,(PIOAD)
        rrca
        rl      e
        djnz    loopspi
        xor     a
	set	S_DI,a		;DI  H
        out    (PIOAD),a
        pop     bc
        ret

get_sector:
	ld	hl,0x0000
	ld	de,DISK_TRACK * DISK_SECTOR	;1 disk sector >> DISK_TRACK * DISK_SECTOR
	ld	a,(disk_number)
	cp	0x00
	jr	z,read_track
	ld	b,a	
read_disk01:
	add	hl,de	
	djnz	read_disk01
read_track:
	ld	de,DISK_SECTOR		;1 track sector >> DISK_SECTOR
	ld	a,(track_number)
	cp	0x00
	jr	z,read_sector
	ld	b,a	
read_track01:
	add	hl,de	
	djnz	read_track01	
read_sector:
	ld	a,(sector_number)
	dec	a
	ld	e,a
	ld	d,0x00
	add 	hl,de
	ret

read:				;read next disk record(assuming disk/trk/sec/dma set)

	call	get_sector		;read block   HL reg

			
        ld      a,(r7)
        bit     6,a
        jp      z,read_SD_ver2
        ld      a,h                    	;SDHC
        ld      (cmd18+03),a
        ld      a,l
        ld      (cmd18+04),a
        jr      spi_read2
read_SD_ver2:
        ld      a,h                    	;Ver2
        ld      (cmd18+02),a
        ld      a,l
        ld      (cmd18+03),a


	ld	hl,(dma_Buff_addr)
spi_read2:

        
        call    dummy_data              ;dummy data(0xff) out
        ld      hl,cmd18
        call    cmd_out                 ;cmd17 Issue
        call    r1_resp
        cp      0x00                    ;response is 0x00 read mode OK?
        jr      nz,cmd18_err
cmd18_st:
        ld      d,0xff
        call    spi_8bit


        call    r1_resp                 ;read data start response?
        cp      0xfe                    ;data start byte 0xfe?
        jr nz,  cmd18_st

        ld      b,0x80                  ;read data size 128byte
        ld	hl,(dma_Buff_addr)      ;read data buff address

cmd18_r:
        call    resp                    ;read data
        ld      (hl),a
        inc     hl
        djnz    cmd18_r

;;	dummy read 128byte 2st 3st 4st

        ld      b,0x80			;read data size 128byte
cmd18_r2st:
        call    resp
        djnz    cmd18_r2st
        ld      b,0x80
cmd18_r3st:
        call    resp
        djnz    cmd18_r3st

        ld      b,0x80
cmd18_r4st:
        call    resp
        djnz    cmd18_r4st

        call    resp                    ;crc Skipping read
        call    resp                    ;crc Skipping read
        ld      d,0xff                  ;dummy data 0xff
        call    spi_8bit


       	ld      hl,cmd12		;stop cmd
        call    cmd_out                 ;cmd12 Issue
	ld	d,0xff
	call	spi_8bit
        call    r1_resp
        cp      0x00                    ;response is 0x00 read mode OK?
        jr      nz,cmd18_err

cmd18_wch3:
	call	resp
	cp	0x00
	jr	z,cmd18_wch3

        call	set_cs		          ;CS="H"
        xor        a
        ret

cmd18_err:
	call	set_cs		          ;CS="H"
	ld	a,0x01
	ret

read512:
					;read 1sector 512byte
        ld	hl,(read512_block_no)   ;read bolck_no
					
        ld      a,(r7)
        bit     6,a
        jp      z,read512_SD_ver2
        ld      a,h                    	;SDHC
        ld      (cmd18+03),a
        ld      a,l
        ld      (cmd18+04),a
        jr      spi_read512_2
read512_SD_ver2:
        ld      a,h                    	;Ver2
        ld      (cmd18+02),a
        ld      a,l
        ld      (cmd18+03),a

spi_read512_2:
        call    dummy_data              ;dummy data(0xff) out
        ld      hl,cmd18
        call    cmd_out                 ;cmd17 Issue
        call    r1_resp
        cp      0x00                    ;response is 0x00 read mode OK?
        jr      nz,cmd18_512_err

sector_read_loop:
cmd18_512_st:
 
        call    r1_resp                 ;read data start response?
        cp      0xfe                    ;data start byte 0xfe?
        jr nz,  cmd18_512_st

 
        ld	hl,(read512_addr)       ;read data buff address
       	ld      b,0x00                  ;read data size 256byte
cmd18_512_r:
        call    resp                    ;read data
        ld      (hl),a
        inc     hl
        djnz    cmd18_512_r

        ld      b,0x00			;2st 256byte write
cmd18_512_r2st:
        call    resp
        ld      (hl),a                  ;read data
        inc     hl
        djnz    cmd18_512_r2st

        ld      (read512_addr),hl

        call    resp                    ;crc Skipping read
        call    resp                    ;crc Skipping read

	ld	hl,(read512_block)
	dec	hl
	ld	(read512_block),hl
	ld	a,h			;HL = 0?
	or	l
	jr	nz,sector_read_loop

        ld      d,0xff                  ;dummy data 0xff(cs low)
        call    spi_8bit

       	ld      hl,cmd12		;stop cmd
        call    cmd_out                 ;cmd12 Issue
	ld	d,0xff
	call	spi_8bit
        call    r1_resp
        cp      0x00                    ;response is 0x00 read mode OK?
        jr      nz,cmd18_512_err

cmd18_512_wch3:
	call	resp
	cp	0x00
	jr	z,cmd18_512_wch3

        call	set_cs		        ;CS="H"
        xor    	a
        ret

cmd18_512_err:
	call	set_cs		         ;CS="H"
	ld	a,0x01
	ret


write:
	call	get_sector
 
spi_write1:
        ld      a,(r7)
        bit     6,a
        jp      z,write_SD_ver2
        ld      a,h                   ;SDHC
        ld      (cmd25+03),a
        ld      a,l
        ld      (cmd25+04),a
        jr      spi_write2
write_SD_ver2:                        ;Ver2
        ld      a,h
        ld      (cmd25+02),a
        ld      a,l
        ld      (cmd25+03),a    


spi_write2:
        call    dummy_data
        ld      hl,cmd25
        call    cmd_out
        call    r1_resp
        cp      0x00
        jp      nz,cmd25_err

        ld      d,0xff
        call    spi_8bit
 
	ld      d,0xfc				;cmd25 data token
        call    spi_8bit

	ld	hl,(dma_Buff_addr)
        ld      b,0x80
cmd25_w:
        ld      d,(hl)
        inc     hl
        call    spi_8bit
        djnz    cmd25_w

;	2st dummy write(0xe5)
 
        ld      b,0x80
cmd25_w2st:
        ld      d,0xe5
        call    spi_8bit
        djnz    cmd25_w2st

;	3st dummy write(0xe5)  
        ld      b,0x80
cmd25_w3st:
        ld      d,0xe5
        call    spi_8bit
        djnz    cmd25_w3st

;	4st dummy write(0xe5)  
        ld      b,0x80
cmd25_w4st:
        ld      d,0xe5
        call    spi_8bit
        djnz    cmd25_w4st

        ld      d,0xff
        call    spi_8bit    ;crc
        ld      d,0xff
        call    spi_8bit    ;crc

        call    r1_resp
        and     0x0f
        cp      0x05
        jr      nz,cmd25_err2
cmd25_wch:
        call    r1_resp
        cp      0x00
        jr      z,cmd25_wch

	ld	d,0xfd			;cmd25 stop token
	call	spi_8bit 	
	ld	d,0xff
	call	spi_8bit
cmd25_wch3:
	call	resp
	cp	0x00
	jr	z,cmd25_wch3

	call	dummy_data
	call	set_cs			;set CS
        xor     a
        ret

cmd25_err:
cmd25_err2:
	call	set_cs			;set cs
	ld	a,0x01
	ret

set_cs:
	xor	a
	set     S_CS,a          ;CS="H"
	set	S_DI,a		;DI="H"
	out    (PIOAD),a
        ret

dummy_data:
        xor     a
        set     S_CS,a          ;CS="H"
        set     S_DI,a          ;DI="H"
        out    (PIOAD),a
        ld      b,8            ;1clok output
        call    loopspii
        xor     a
	set     S_CS,a          ;CS="H"	
	set	S_DI,a		;CS="H"
        out    (PIOAD),a
        ret
loopspii:
        res     S_CLK,a         ;CLK    L
        out    (PIOAD),a
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop

        set     S_CLK,a         ;CLK    H
        out    (PIOAD),a
        nop
        nop
        nop
        nop
        nop
        djnz    loopspii
        ret

msgout:
        ld      a,(hl)          ;(HL)reg is output disp at 0x00
        cp      0x00
        ret     z
        call    putchar
        inc     hl
        jr      msgout

siobinit:
	ld	b,12
	ld	hl,SIO_init_data
sioainit01:
	ld	a,(HL)
	out	(SIOBC),a
	inc	hl
	djnz	sioainit01
	ret

pioainit:
	ld	b,3
	ld	hl,PIO_init_data
pioainit01:
	ld	a,(HL)
	out	(PIOAC),a
	inc	hl
	djnz	pioainit01
	ret	

SIO_init_data:
	.db	0x00,0b00110000		;WR0=WR0:set ,WR0: err reset
	.db	0x01,0b00000000		;WR0=WR1:set ,WR1: all int reset
	.db	0x02,0b00000000		;WR0=WR2:set ,WR2: CH-B int set
	.db	0x03,0b11000001		;WR0=WR3:set ,WR3: RxBit=8bit Rx=ready
	.db	0x04,0b01000100		;WR0=WR4:set ,WR4: clck=exIN*1 stop=1bit parity=non
	.db	0x05,0b11101010		;WR0=WR5:set ,WR5: char=8bit hardware flow=non Tx=ready
			 
PIO_init_data:
	.db	0b11001111		;PIOAC:set 0xcf: Mode3 (bit mode)
	.db	0b00011111		;PIOAC:set 0x1f: D4-D0=input D7-D5=output
	.db	0b00000000		;PIOAC:set 0x00: interrupt disables



sdhc_msg:
        .str    ":SDHC"
        .db     0x0d
        .db     0x00    
sd_ver2_msg:
        .str    ":SD Ver2"
        .db     0x0d
        .db     0x00
spi_init_err_msg:
        .str    "Spi Init Err"
        .db     0x0d
        .db     0x00  

cmd0:                           ;;48bit(6byte) Fixed length 
        .db     0x40            ;;command index 
        .db     0x00            ;;argument
        .db     0x00            ;;argument
        .db     0x00            ;;argument
        .db     0x00            ;;argument
        .db     0x95            ;;CRC  
cmd8:
        .db     0x48
        .db     0x00
        .db     0x00
        .db     0x01
        .db     0xaa
        .db     0x87
cmd55:
        .db     0x77
        .db     0x00
        .db     0x00
        .db     0x00
        .db     0x00
        .db     0xff
acmd41:
        .db     0x69
        .db     0x40
        .db     0xff
        .db     0x80
        .db     0x00
        .db     0xff
cmd58:
        .db     0x7a
        .db     0x00
        .db     0x00
        .db     0x00
        .db     0x00
        .db     0xff

cmd16:
        .db     0x50
        .db     0x00
        .db     0x00
        .db     0x02
        .db     0x00
        .db     0xff

cmd18:
        .db     0x52
        .db     0x00
        .db     0x00
        .db     0x00
        .db     0x00
        .db     0xff
cmd12:
        .db     0x4c
        .db     0x00
        .db     0x00
        .db     0x00
        .db     0x00
        .db     0xff

cmd25:
        .db     0x59
        .db     0x00
        .db     0x00
        .db     0x00
        .db     0x00
        .db     0xff

r7:
        .ds     4 


;	scratch ram area for bdos use
;begdat	equ	$	 	;beginning of data area
dirbf:	.ds	128	 	;scratch directory area
all00:	.ds	31	 	;allocation vector 0
all01:	.ds	31	 	;allocation vector 1
all02:	.ds	31	 	;allocation vector 2
all03:	.ds	31	 	;allocation vector 3
chk00:	.ds	16		;check vector 0
chk01:	.ds	16		;check vector 1
chk02:	.ds	16	 	;check vector 2
chk03:	.ds	16	 	;check vector 3

dma_Buff_addr:	.dw	BUFF_DEFAULT_ADDR	;dma buff address
sector_number:	.db	0x01			;sector number			
track_number:	.db	TRACK_OFFSET		;track number
disk_number:	.db	0x00			;disk number
old_disk_number:	.dw	0x00		;old disk number
read512_addr:	.dw	0xdc00			;system top addr(512byte read)
read512_block_no: .dw	0x0000			;system top sector no. (512byte read)
read512_block:	.dw	0x000b			;0x1600(ccp+BDOS) /512byte(sector)
	.end


おすすめの記事