	title	'Customized Basic I/O System'

;*********************************************
;*                                           *
;* This Customized BIOS adapts CP/M-86 to    *
;* the following hardware configuration      *
;*     Processor:                            *
;*     Brand:                                *
;*     Controller:                           *
;*                                           *
;*                                           *
;*     Programmer:                           *
;*     Revisions :                           *
;*                                           *
;*********************************************

true		equ -1
false		equ not true
cr		equ 0dh ;carriage return
lf		equ 0ah ;line feed

;*********************************************
;*                                           *
;* Loader_bios is true if assembling the     *
;* LOADER BIOS, otherwise BIOS is for the    *
;* CPM.SYS file.                             *
;*                                           *
;*********************************************

loader_bios	equ false
bdos_int	equ 224 ;reserved BDOS interrupt

	IF	not loader_bios
;---------------------------------------------
;|                                           |
bios_code	equ 2500h
ccp_offset	equ 0000h
bdos_ofst	equ 0B06h ;BDOS entry point
;|                                           |
;---------------------------------------------
	ENDIF	;not loader_bios

	IF	loader_bios
;---------------------------------------------
;|                                           |
bios_code	equ 1200h ;start of LDBIOS
ccp_offset	equ 0003h ;base of CPMLOADER
bdos_ofst	equ 0406h ;stripped BDOS entry
;|                                           |
;---------------------------------------------
	ENDIF	;loader_bios

	cseg
	org	ccpoffset
ccp:
	org	bios_code

;*********************************************
;*                                           *
;* BIOS Jump Vector for Individual Routines  *
;*                                           *
;*********************************************

 jmp INIT	;Enter from BOOT ROM or LOADER
 jmp WBOOT	;Arrive here from BDOS call 0  
 jmp CONST	;return console keyboard status
 jmp CONIN	;return console keyboard char
 jmp CONOUT  	;write char to console device
 jmp LISTOUT	;write character to list device
 jmp PUNCH	;write character to punch device
 jmp READER  	;return char from reader device 
 jmp HOME	;move to trk 00 on cur sel drive
 jmp SELDSK  	;select disk for next rd/write
 jmp SETTRK  	;set track for next rd/write
 jmp SETSEC  	;set sector for next rd/write
 jmp SETDMA  	;set offset for user buff (DMA)
 jmp READ	;read a 128 byte sector
 jmp WRITE	;write a 128 byte sector
 jmp LISTST  	;return list status 
 jmp SECTRAN 	;xlate logical->physical sector 
 jmp SETDMAB 	;set seg base for buff (DMA)
 jmp GETSEGT 	;return offset of Mem Desc Table
 jmp GETIOBF	;return I/O map byte (IOBYTE)
 jmp SETIOBF	;set I/O map byte (IOBYTE) 

;*********************************************
;*                                           *
;* INIT Entry Point, Differs for LDBIOS and  *
;* BIOS, according to "Loader_Bios" value    *
;*                                           *
;*********************************************

INIT:	;print signon message and initialize hardware
	mov ax,cs	;we entered with a JMPF so use
	mov ss,ax	;CS: as the initial value of SS:,
	mov ds,ax	;DS:,
	mov es,ax	;and ES:
	;use local stack during initialization
	mov sp,offset stkbase
	cld		;set forward direction

	IF	not loader_bios
;---------------------------------------------
;|                                           |
	; This is a BIOS for the CPM.SYS file.
	; Setup all interrupt vectors in low
	; memory to address trap

	push ds		;save the DS register
	mov IOBYTE,0	;clear IOBYTE
	mov ax,0
	mov ds,ax
	mov es,ax 	;set ES and DS to zero
	;setup interrupt 0 to address trap routine
	mov int0_offset,offset int_trap
	mov int0_segment,CS
	mov di,4
	mov si,0	;then propagate
	mov cx,510	;trap vector to
	rep movs ax,ax	;all 256 interrupts
	;BDOS offset to proper interrupt
	mov bdos_offset,bdos_ofst
	pop ds		;restore the DS register

;	(additional CP/M-86 initialization)
;|                                           |
;---------------------------------------------
	ENDIF	;not loader_bios

	IF	loader_bios
;---------------------------------------------
;|                                           |
	;This is a BIOS for the LOADER
	push ds		;save data segment
	mov ax,0
	mov ds,ax	;point to segment zero
	;BDOS interrupt offset
	mov bdos_offset,bdos_ofst
	mov bdos_segment,CS ;bdos interrupt segment
;	(additional LOADER initialization)
	pop ds		;restore data segment
;|                                           |
;---------------------------------------------
	ENDIF	;loader_bios

	mov bx,offset signon
	call pmsg	;print signon message
	mov cl,0	;default to dr A: on coldstart
	jmp ccp		;jump to cold start entry of CCP

WBOOT:	jmp ccp+6	;direct entry to CCP at command level

	IF	not loader_bios
;---------------------------------------------
;|                                           |
int_trap:
	cli		;block interrupts
	mov ax,cs
	mov ds,ax	;get our data segment
	mov bx,offset int_trp
	call pmsg
	hlt		;hardstop
;|                                           |
;---------------------------------------------
	ENDIF	;not loader_bios

;*********************************************
;*                                           *
;*   CP/M Character I/O Interface Routines   *
;*                                           *
;*********************************************

CONST:		;console status
	rs	10	;(fill-in)
	ret

CONIN:			;console input
	call CONST
	jz CONIN	;wait for RDA
	rs	10	;(fill-in)
	ret

CONOUT:		;console output
	rs	10	;(fill-in)
	ret		;then return data

LISTOUT:		;list device output
	rs	10	;(fill-in)
	ret

LISTST:			;poll list status
	rs	10	;(fill-in)
	ret

PUNCH:		;write punch device
	rs	10	;(fill-in)
	ret

READER:
	rs	10	;(fill-in)
	ret

GETIOBF:
	mov al,IOBYTE
	ret

SETIOBF:
	mov IOBYTE,cl	;set iobyte
	ret		;iobyte not implemented

pmsg:
	mov al,[BX] 	;get next char from message
	test al,al
	jz return	;if zero return
	mov CL,AL
	call CONOUT  	;print it
	inc BX
	jmps pmsg	;next character and loop

;*********************************************
;*                                           *
;*          Disk Input/Output Routines       *
;*                                           *
;*********************************************

SELDSK:		;select disk given by register CL
ndisks	equ	2 ;number of disks (up to 16)
	mov disk,cl	;save disk number
	mov bx,0000h	;ready for error return
	cmp cl,ndisks	;n beyond max disks?
	jnb return	;return if so
	mov ch,0	;double(n)
	mov bx,cx	;bx = n
	mov cl,4	;ready for *16
	shl bx,cl	;n = n * 16
	mov cx,offset dpbase
	add bx,cx	;dpbase + n * 16
return:	ret		;bx = .dph

HOME:	;move selected disk to home position (Track 0)
	mov trk,0	;set disk i/o to track zero
	rs	10	;(fill-in)
	ret

SETTRK: ;set track address given by CX
	mov trk,CX
	ret

SETSEC: ;set sector number given by cx
	mov sect,CX
	ret

SECTRAN: ;translate sector CX using table at [DX]
	mov bx,cx
	add bx,dx	;add sector to tran table address
	mov bl,[bx]	;get logical sector
	ret

SETDMA: ;set DMA offset given by CX
	mov dma_adr,CX
	ret

SETDMAB: ;set DMA segment given by CX
	mov dma_seg,CX
	ret
;
GETSEGT:  ;return address of physical memory table
	mov bx,offset seg_table
	ret

;*********************************************
;*                                           *
;*  All disk I/O parameters are setup:       *
;*     DISK     is disk number      (SELDSK) *
;*     TRK      is track number     (SETTRK) *
;*     SECT     is sector number    (SETSEC) *
;*     DMA_ADR  is the DMA offset   (SETDMA) *
;*     DMA_SEG  is the DMA segment  (SETDMAB)*
;*  READ reads the selected sector to the DMA*
;*  address, and WRITE writes the data from  *
;*  the DMA address to the selected sector   *
;*  (return 00 if successful,  01 if perm err)*
;*                                           *
;*********************************************

READ:
	rs	50	;fill-in
	ret

WRITE:
	rs	50	;(fill-in)
	ret


;*********************************************
;*                                           *
;*               Data Areas                  *
;*                                           *
;*********************************************
data_offset	equ offset $

	dseg
	org	data_offset	;contiguous with code segment
IOBYTE	db	0
disk	db	0	;disk number
trk	dw	0	;track number
sect	dw	0	;sector number
dma_adr	dw	0	;DMA offset from DS
dma_seg	dw	0	;DMA Base Segment

	IF	loader_bios
;---------------------------------------------
;|                                           |
signon 	db	cr,lf,cr,lf
	db	'CP/M-86 Version 1.0',cr,lf,0
;|                                           |
;---------------------------------------------
	ENDIF	;loader_bios

	IF	not loader_bios
;---------------------------------------------
;|                                           |
signon	db	cr,lf,cr,lf
	db	'System Generated 00/00/00'
	db	cr,lf,0
;|                                           |
;---------------------------------------------
	ENDIF	;not loader_bios

int_trp	db	cr,lf
	db	'Interrupt Trap Halt'
	db	cr,lf

;	System Memory Segment Table

segtable db 2	;2 segments
	dw tpa_seg	;1st seg starts after BIOS
	dw tpa_len	;and extends to 08000
	dw 2000h	;second is 20000 -
	dw 2000h	;3FFFF (128k)

	include singles.lib ;read in disk definitions

loc_stk	rw  32	;local stack for initialization
stkbase	equ offset $

lastoff	equ offset $
tpa_seg	equ (lastoff+0400h+15) / 16
tpa_len	equ 0800h - tpa_seg
	db 0	;fill last address for GENCMD

;*********************************************
;*                                           *
;*          Dummy Data Section               *
;*                                           *
;*********************************************
	dseg	0	;absolute low memory
	org 	0	;(interrupt vectors)
int0_offset	rw	1
int0_segment	rw	1
;	pad to system call vector
	rw	2*(bdos_int-1)

bdos_offset	rw	1
bdos_segment	rw	1
	END
