CR	EQU	0Dh
LF	EQU	0Ah
FNAMELG	EQU	40h
MACHINE	EQU	0h;0h:PC-9821 / 1h PC/AT compatible
INCLUDE	DEBUGLIB.INC

IF	MACHINE	EQ	0h
IODELAY	EQU	5Fh
ELSE
IODELAY	EQU	0EBh
ENDIF
	
CODE	SEGMENT
	ASSUME	CS:CODE,DS:CODE,SS:CODE
;	ORG	0100h
	.586p
START:
DEVHDR	DD	0FFFFFFFFh	;次のデバイスドライバへのポインタ
				;（チェインポインタ）
				;0FFFFFFFFh(-1)は最後のデバイスのとき
	DW	0C000h		;デバイスアトリビュート
	DW	OFFSET STRTG	;ストラテジ・ルーチンへのポインタ
	DW	OFFSET INTRP	;インタラプト・ルーチンへのポインタ
NMFLD	DB	'SCSIMGR$'	;8バイトのキャラクタ型デバイスのname field
	DW	0		;予約(必ず0)
	DB	0		;ドライブレター(必ず0)
UNITN	DB	1		;サポートするユニット数(1以上)

STRTG:	MOV	WORD PTR CS:[PREQHED],BX
	MOV	WORD PTR CS:[PREQHED + 2],ES
	RETF
PREQHED	DB	4 DUP(0)	;リクエストヘッダへのポインタ

STCOFST	DW	0h
STCSGMT	DW	0h

INTRP:	PUSHF
	PUSHA
	PUSH	DS
	PUSH	ES
	MOV	WORD PTR CS:STCOFST,SP	;スタックポインタの退避
	MOV	WORD PTR CS:STCSGMT,SS
	CLI
	MOV	SP,OFFSET INIT	;-1
	MOV	AX,CS
	MOV	SS,AX
	STI

	LDS	SI,DWORD PTR CS:PREQHED
	MOV	AL,BYTE PTR DS:[SI+2]	;コマンドコードの取得
	TEST	AL,AL
	JZ	INIT
	CMP	AL,03h
	MOV	AX,8103h;UNKOWN COMMAND
	JNZ	RETSTAT

	LES	DI,DWORD PTR DS:[SI+0Eh];TRANSFER ADDRESS
	MOV	WORD PTR ES:[DI],006Eh
	MOV	AX,WORD PTR CS:BIOSSEG
	MOV	WORD PTR ES:[DI+02h],AX
NMLEND:
	MOV	AX,0100h;正常終了
RETSTAT:
	LDS	SI,DWORD PTR CS:PREQHED
	MOV	DS:[SI+03h],AX

	CLI
	LSS	SP,DWORD PTR CS:STCOFST
	STI

	POP	ES
	POP	DS
	POPA
	POPF
	RETF
BIOSSEG	DW	0h

	EVEN
	DB	200 DUP(0h)
INIT:	;PUSH	DS

	MOV	WORD PTR DS:[SI+16],CS
	MOV	BYTE PTR DS:[SI+13],0h	;サポートするユニット数

;***********************************************
;	INVOCATION LINEから引数の取得
;Get ARGument
;***********************************************
	LES	DI,DWORD PTR DS:[SI+18]	;BPBを指すポインタ
	XOR	CX,CX
	MOV	AL,0Dh	;行末まで何文字あるか

GARG1:	INC	CX
;	REPNZ	SCASB
	SCASB
	JNZ	GARG1
;	NEG	CX;何文字目で0Dhに当たったか
;	MOV	DX,DI;DXは0Dhのあるアドレスを指す
	SUB	DI,CX
	DEC	CX	;0Dhを指した瞬間に終了

GARG4:	MOV	AL,'/'
	REPNZ	SCASB
	JCXZ	GARG3	;CX=0なら何でも抜ける。現在'/'の直後を指す

	MOV	AL,BYTE PTR ES:[DI]
	AND	AL,0DFh	;小文字->大文字

;'/C:10950680'
GARG2:	CMP	AL,'P'	;チップ所在
	JNZ	GARG5	;知らんオプションは無視
	INC	DI;':'を飛ばす
	INC	DI
	SUB	CX,02h
	JC	GARG3	;CX=0なら問答無用で抜ける
	MOV	EAX,DWORD PTR ES:[DI]
	MOV	DWORD PTR CS:CHIPPOS,EAX
	MOV	EAX,DWORD PTR CS:CHIPPOS;INT 1AhのBX
	CALL	A2B
	MOV	CS:BX1394,DX
	SUB	CX,04h
	JC	GARG3
	ADD	DI,04h
	JMP	GARG4

GARG5:	CMP	AL,'S'	;スロット所在
	JNZ	GARG4	;知らんオプションは無視
	INC	DI;':'を飛ばす
	INC	DI
	SUB	CX,02h
	JC	GARG3	;CX=0なら問答無用で抜ける
	MOV	AL,BYTE PTR ES:[DI]
	SUB	AL,'0'
	CMP	AL,01h
	JA	GARGS1;デフォルトになる
	MOV	BYTE PTR CS:SLOTID,AL;SLOT 0:下段、SLOT 1:上段

GARGS1:	DEC	CX
	JC	GARG3	;CX=0なら問答無用で抜ける
	INC	DI
	JMP	GARG4

GARG3:
	
	PUSH	CS
	POP	DS
;***********************************************
;	PCI-BIOSを用いたリソースの取得
;***********************************************
;DS:[SI]:リクエストパケット ES:[DI]:BPB CS:[SI]:デバイス名
	MOV	AX,0B103h
	XOR	SI,SI
	MOV	ECX,00060700h;PCI-Cardbus bridge
	INT	1Ah
	MOV	DX,OFFSET NOCHIP
	JC	ERRMSG
	OR	AH,AH
	JNZ	ERRMSG

	MOV	WORD PTR DS:CBPOS,BX

;配下バス番号の割り当て
	MOV	AX,0B10Ah
	MOV	DI,18h
	INT	1Ah
	AND	ECX,0FF000000h
	MOV	AX,0B10Dh
	OR	ECX,010100h;Bus=1,Subordinate bus=1
	INT	1Ah

	INC	BL;function=1

	MOV	AX,0B10Ah
	MOV	DI,18h
	INT	1Ah
	AND	ECX,0FF000000h
	MOV	AX,0B10Dh
	OR	ECX,020200h;Bus=2,Subordinate bus=2
	INT	1Ah

	CALL	CBSETRES;リソース割り当て

	MOV	BX,OFFSET GDT0
	MOV	EAX,CBCTRL;00F00000h;DWORD PTR DS:MEMIO
	PUSH	CS
	POP	ES
	ROL	EAX,08h
	MOV	BYTE PTR DS:[BX+17h],AL
	MOV	BYTE PTR DS:[BX+4Fh],AL
	SHR	EAX,08h
	OR	DWORD PTR DS:[BX+12h],EAX
	OR	DWORD PTR DS:[BX+4Ah],EAX

	XOR	AX,AX
	CALL	LADR
;	ROL	EAX,08h
;	MOV	WORD PTR DS:[BX+17h],AL
;	MOV	WORD PTR DS:[BX+37h],AL
;	SHR	EAX,08h
	OR	DWORD PTR DS:[BX+1Ah],EAX
	OR	DWORD PTR DS:[BX+42h],EAX

;
	MOV	DI,+08h
	CALL	MMIOR
	TEST	AL,20h;CardBus Cardが挿さっているか
	JZ	RETDOS
	TEST	AH,08h
	MOV	CL,30h;3h;Vcc=3.3V , Vpp=Vcc
	JNZ	VCON
	TEST	AH,04h
	MOV	CL,20h;2h;Vcc=5.0V , Vpp=Vcc
	JZ	RETDOS

VCON:	MOV	DI,+10h
	CALL	MMIOR
	AND	AL,88h
	OR	AL,CL
	CALL	MMIOW
	
	MOV	DX,03E0h
	MOV	AL,02h
	OUT	DX,AL
	INC	DX
	MOV	AL,9Ch
	OUT	DX,AL

	MOV	DX,03E0h
	MOV	AL,03h
	OUT	DX,AL
	INC	DX
	MOV	AL,10h
	OUT	DX,AL

	MOV	DX,03E0h
	MOV	AL,42h
	OUT	DX,AL
	INC	DX
	MOV	AL,9Ch
	OUT	DX,AL

	MOV	DX,03E0h
	MOV	AL,43h
	OUT	DX,AL
	INC	DX
	MOV	AL,10h
	OUT	DX,AL
;給電されてデバイスが見えるようになる

	MOV	BX,WORD PTR DS:CBPOS
	OR	BL,BYTE PTR DS:SLOTID;SLOT 0:下段、SLOT 1:上段
	MOV	DI,3Eh
	MOV	AX,0B10Bh
	MOV	CL,40h;CARDBUS RESET=1
	INT	1Ah
	
	MOV	CX,08h
MACHI4:	PUSH	CX
	XOR	CX,CX
MACHI3:	OUT	5Fh,AL
	LOOP	MACHI3
	POP	CX
	LOOP	MACHI4

	MOV	DI,3Eh
	MOV	AX,0B10Bh
	MOV	CL,00h;CARDBUS RESET=0
	INT	1Ah

	MOV	CX,8h
MACHI2:	PUSH	CX
	XOR	CX,CX
MACHI1:	OUT	5Fh,AL
	LOOP	MACHI1
	POP	CX
	LOOP	MACHI2

	CALL	SETRES

	LDS	SI,DWORD PTR CS:PREQHED
	MOV	AX,800Ch
	MOV	WORD PTR DS:[SI+14],0h	;終了アドレス
RETDOS:	JMP	RETSTAT

NOCHIP	DB	'PCI-CardBus bridgeが見つかりません',CR,LF,'$'
NOOHCI	DB	'1394OHCIが見つかりません',CR,LF,'$'
ERRMSG:	PUSH	CS
	POP	DS
	MOV	AH,09h
	INT	21h
	JMP	RETDOS;RETF

LADR:	PUSH	EBX
	XOR	EBX,EBX
	MOV	BX,AX
	XOR	EAX,EAX
	MOV	AX,CS
	SHL	EAX,4h
	ADD	EAX,EBX
	POP	EBX
	RET

CBSETRES:
	MOV	BX,WORD PTR DS:CBPOS
	OR	BL,BYTE PTR DS:SLOTID;SLOT 0:下段、SLOT 1:上段

	MOV	AX,0B108h
	MOV	DI,04h;COMMAND REGISTER
	INT	1Ah
	OR	CL,0FFh;02h
	MOV	AX,0B10Bh
	INT	1Ah

	MOV	AX,0B10Dh
	MOV	ECX,CBCTRL;00F00000h
	MOV	DI,10h
	INT	1Ah

	MOV	AX,0B10Bh
	MOV	CL,BYTE PTR CS:INTLINE
	MOV	DI,3Ch
	INT	1Ah

	MOV	ECX,DWORD PTR CS:IOADR
	MOV	AL,2Ch;I/O Window 0 base
	CALL	CONFWD
	MOV	AL,30h;I/O Window 0 limit
	ADD	ECX,28h;CardBusではI/O空間は4h置き
	CALL	CONFWD
	MOV	AL,34h;I/O Window 1 base
	MOV	ECX,0FFFCh
	CALL	CONFWD

	MOV	ECX,DWORD PTR CS:MEMADR
	MOV	AL,1Ch;Mem Window 0 base
	CALL	CONFWD
	MOV	AL,20h;Mem Window 0 limit
	ADD	ECX,1000h;CardBusではメモリ空間は1000h置き
	CALL	CONFWD
	MOV	AL,24h;Mem Window 1 base
	MOV	ECX,-1
	CALL	CONFWD
	RET

OUT18F0:
	MOV	DX,18F0h
	MOV	AX,0017h
	OUT	DX,AX
	INC	DX
	INC	DX;DX=18F2h
	IN	AX,DX
	RET

SETRES:
	CALL	OUT18F0
	OR	AL,01
	OUT	DX,AX

	MOV	AL,2Fh
	OUT	0A1h,AL
	MOV	AL,57h
	OUT	0A3h,AL
	MOV	AL,09h
	OUT	0A5h,AL

	MOV	AL,02h
	OUT	0A9h,AL;最大バス番号

	CALL	OUT18F0
	AND	AL,0FEh
	OUT	DX,AX

;1394OHCI検索
	MOV	BX,WORD PTR DS:BX1394
	OR	BX,BX
	JZ	DEV_SEARCH
	MOV	AX,0B10Ah
	MOV	DI,08h
	INT	1Ah
	XOR	CL,CL
	CMP	ECX,0C001000h
	JNZ	DEV_NOT_FOUND
	JMP	DEV_FOUND

DEV_SEARCH:
	MOV	AX,0B103h
	XOR	SI,SI
	MOV	ECX,000C0010h;OHCI仕様IEEE1394
	INT	1Ah
	JC	DEV_NOT_FOUND
	OR	AH,AH
	JNZ	DEV_NOT_FOUND
	MOV	WORD PTR DS:BX1394,BX;Bus,device,function番号を保存
DEV_FOUND:

;	MOV	BX,103h
	MOV	CL,BYTE PTR CS:INTLINE
	MOV	DI,3Ch;Interrupt Line
	MOV	AX,0B10Bh
	INT	1Ah
	MOV	CL,08h
	MOV	DI,0Ch;Cache Line Size
	MOV	AX,0B10Bh
	INT	1Ah

	MOV	ECX,DWORD PTR CS:MEMADR;200h置きのメモリ空間
	MOV	AL,10h;10h 08h BYTES
	CALL	CONFWD

;	MOV	AX,0B10Dh
	MOV	ECX,06;-1h
	MOV	AL,04h
;	CALL	CONFWD
;	RET

CONFWD:	;MOV	BX,WORD PTR CS:CHIPPOS
	MOVZX	DI,AL
	MOV	AX,0B10Dh;WRITE DWORD
	INT	1Ah
SETRESRET:	RET
DEV_NOT_FOUND:
	MOV	DX,OFFSET NOOHCI
	JMP	ERRMSG
;メモリマップトIO
;引数DI:オフセット
MMIOC:	PUSH	ES
	PUSH	CS
	POP	ES
	PUSHF
	CLI
	MOV	AH,90h
	MOV	CX,04h
	INT	1Fh
	POPF
	POP	ES
	RET

MMIOW:	PUSH	DS
	PUSH	0DC00h
	POP	DS
	MOV	DWORD PTR DS:[DI],EAX
	POP	DS
	RET
	PUSHA
	MOV	SI,OFFSET QUADLET
	MOV	DWORD PTR DS:[SI],EAX
	MOV	BX,OFFSET GDT1
	CALL	MMIOC
	POPA
	RET

MMIOR:	PUSH	DS
	PUSH	0DC00h
	POP	DS
	MOV	EAX,DWORD PTR DS:[DI]
	POP	DS
	RET

;  IFDEF	HOGE
	PUSHA

	MOV	SI,OFFSET QUADLET
	MOV	BX,OFFSET GDT0
	XCHG	SI,DI
	CALL	MMIOC
	POPA
	MOV	EAX,DWORD PTR DS:QUADLET
	RET
DEBUGLIB
;READ用のGDT
	ALIGN	8
GDT0	DB	16 DUP(00h)
	DB	0FFh,0FFh,00,00,00,93h,0FFh,00h;DS用セグメント
	DB	0FFh,0FFh,00,00,00,93h,00,00;ES用セグメント
	DW	0
	DB	00,00,00,9Bh,00,00;CSでアクセス
	DB	0,0,00,00,00,9Bh,00,00;CSでアクセス
;WRITE用のGDT
;	ALIGN	8
GDT1	DB	16 DUP(00h)
	DB	0FFh,0FFh,00,00,00,93h,00h,00h;DS用セグメント
	DB	0FFh,0FFh,00,00,00,93h,0FFh,00h;ES用セグメント
	DW	0
	DB	00,00,00,9Bh,00,00;CSでアクセス
	DB	0,0,00,00,00,9Bh,00,00;CSでアクセス
QUADLET	DD	0h
CBPOS	DW	0h
INTLINE	DB	03h
IOADR	DD	6800h
MEMADR	DD	0DD000h;20000000h
BX1394	DW	0h
CBCTRL	DD	0DC000h
CHIPPOS	DD	0h
SLOTID	DB	1h;デフォルトは上段

;************ASCII TO BINARY BYTE*******************
A2B:	;EAX(ASCII)->DX(HEXADECIMAL)
	PUSH	CX
	MOV	CX,04h
	XOR	DX,DX
A2B2:	CMP	AL,40h	;大ならA-Fh/小なら0-9h
	JB	A2B1
	ADD	AL,09h
A2B1:	AND	AL,0Fh
	OR	DL,AL
	ROL	DX,04h
	SHR	EAX,08h
	LOOP	A2B2
	POP	CX
	ROR	DX,04h
	RET

CODE	ENDS
	END	START