movlop          ;Copy the data
        lxi     h,djread
        jmp     prep            ;Select drive, track, and 
                                ;  sector. Then read the 
                 

*************************************************************
*                                                           *
* Mover moves 128 bytes of data. Source pointer in DE, Dest *
* pointer in HL.                                            *
*                                                           *
       *
*************************************************************

CONIN:                          ;READ A CHARACTER
        IN      03H
        ANI     02H
        JZ      CONIN           ;WAIT TILL A CHARACTER IS 
                                ; READY
        IN      02H             ;GET THE CHARACTER
        ANI     7FH             ;STRIP PARITY
        RET

*************************************************************
*                                                           *
* L    *
*                                                           *
*************************************************************

flushA  mvi     a,0             ;The 0 is modified to reflect
                                ;  if the buffer has been 
                                ;  written into
bufwrtn equ     $-1
        ana     a               ;Test if written into
        rz                      ;Not written, all done
        lxi     h,djwrite       ;Write operation

*********************a             ;C <- side #
        call    djside          ;Select the side
        pop     psw             ;A <- sector #
        ani     7fh             ;Strip off side bit
        mov     c,a             ;C <- sector #
        call    djsec           ;Set the sector to transfer
        lxi     b,buffer        ;Set the DMA address
        call    djdma
        call    djread          ;The read operation is 
                                ;  modified to write
retryop equ     $-2
        pop    
*************************************************************

mover   mvi     b,128           ;Length of transfer
movlop  ldax    d               ;Get a byte of source
        mov     m,a             ;Move it
        inx     d               ;Bump pointers
        inx     h
        dcr     b               ;Update counter
        jnz     movlop          ;Continue moving until done
        ret

        PAGE
*************************************************************
*                          EFT SERIAL PORT ROUTINES.  CONSOLE OUTPUT                *
*                                                           *
*************************************************************

CONOUT:                         ;WRITE A CHARACTER
        IN      03H
        ANI     01H
        JZ      CONOUT          ;WAIT TILL THE BUFFER IS 
                                ; EMPTY
        MOV     A,C             ;WRITE THE CHARACTER
        OUT     02H
        RET

********************************************************************************
*                                                           *
* Prep prepares to read/write the disk. Retries are         *
* attempted.Upon entry, H&L must contain the read or write  *
* operation address.                                        *
*                                                           *
*************************************************************

prep    xra     a               ;Reset buffer written flag
        sta     bufwrtn
      b               ;Restore the retry counter
        mvi     a,0             ;No error exit status
        rnc                     ;Return no error
        dcr     b               ;Update the retry counter
        stc                     ;Assume retry count expired
        mvi     a,0ffh          ;Error return
        rz
        jmp     retrylp         ;Try again

        PAGE
*************************************************************
*                                                                                            *
* Terminal driver subroutines. Iobyte is not used.          *
* Note that the console device is NOT the DJ2D memory       *
* mapped serial I/O port. The NorthStar serial port is      *
* used instead.                                             *
*                                                           *
*************************************************************

        ;I/O ROUTINES FOR NORTHSTAR MOTHERBOARD

********************************************************************************************
*                                                           *
* The following DPB defines a diskette as 512 byte sectors, *
* double density, and single sided.                         *
*                                                           *
*************************************************************

dpb512s dw      60              ;CP/M sectors/track
        db      4               ;BSH
        db      15              ;BLM
        db      0    ;8 if double sided.

        PAGE
*************************************************************
*                                                           *
* The following DPB defines a diskette for 128 byte sectors,*
* single density, and double sided.                         *
*                                                           *
*************************************************************

dpb128d dw      52              ;CP/M sectors/track
        db      4               ;BSH
************************************************

dpb512d dw      120             ;CP/M sectors/track
        db      4               ;BSH
        db      15              ;BLM
        db      0               ;EXM
        dw      561             ;DSM
        dw      255             ;DRM
        db      0f0h            ;AL0
        db      0               ;AL1
        dw      64              ;CKS
        dw      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        db      3bh

*******
        dw      alv0            ;Allocation vector
	DW	DIRBCB		;DIRECTORY BUFFER CONTROL 
				;  BLOCK
	DW	0FFFFH		;DTABCB DATA BUFFER CONTROL 
				;  BLOCK
	DW	0FFFFH		;HASH DIRECTORY HASHING TABLE
	DB	0		;HBANK BANK # OF HASH TABLE	

dpone   dw      0
        dw      0,0,0,0
        DB	0
	DB	0
        dw      0
        dw      csv1
        dw      alv1
	DW	DIRBCB
	DW	0FFFFH
	DW	0FFFFH
	DB	0

dptwo   dw      0
        dw      0,0,0,0
        DB	0
	DB	0
        dw      0
        d               ;EXM
        dw      280             ;DSM
        dw      127             ;DRM
        db      0c0h            ;AL0
        db      0               ;AL1
        dw      32              ;CKS
        dw      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        db      33h             ;16*((#cpm sectors/physical 
                                ;sector) -1) + log2(#bytes 
                                ;per sector/128) + 1 + 8 
                                ;if double sid        db      15              ;BLM
        db      1               ;EXM
        dw      242             ;DSM
        dw      127             ;DRM
        db      0c0h            ;AL0
        db      0               ;AL1
        dw      32              ;CKS
        dw      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        db      9h

*************************************************************
*                                                           *
* The following DPB defin******************************************************
*                                                           *
* The following DPB defines a diskette as 1024 byte sectors,*
* double density, and double sided.                         *
*                                                           *
*************************************************************

dp1024d dw      128             ;CP/M sectors/track
        db      4               ;BSH
        db      15              ;BLM
        dbw      csv2
        dw      alv2
	DW	DIRBCB
	DW	0FFFFH
	DW	0FFFFH
	DB	0

dpthre  dw      0
        dw      0,0,0,0
        DB	0
	DB	0
        dw      0
        dw      csv3
        dw      alv3
	DW	DIRBCB
	DW	0FFFFH
	DW	0FFFFH
	DB	0


*************************************************************
*                                                           *
*  DIRECTORY BUFFER CONTROL BLOCK                           *
*                                                           *
*****ed.

*************************************************************
*                                                           *
* The following DPB defines a diskette as 1024 byte sectors,*
* double density, and single sided.                         *
*                                                           *
*************************************************************

dp1024s dw      64              ;CP/M sectors/track
        db      4               ;BSH
        db      15              ;Bes a diskette as 256 byte sectors, *
* double density, and double sided.                         *
*                                                           *
*************************************************************

dpb256d dw      104             ;CP/M sectors/track
        db      4               ;BSH
        db      15              ;BLM
        db      0               ;EXM
        dw      486             ;DSM
        dw      255             ;DRM
        db      0f0h            ;AL0
        0               ;EXM
        dw      599             ;DSM
        dw      255             ;DRM
        db      0f0h            ;AL0
        db      0               ;AL1
        dw      64              ;CKS
        dw      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        db      7ch

        PAGE
*************************************************************
*                                                           *
* CP/M disk parameter headers, (FOR 4 DRIVES)             ********************************************************

DIRBCB: DB	0FFH		;DRV  DRIVE NUMBER
	DB	00,00,00	;REC# RECORD POSITION IN
				;  BUFFER
	DB	00		;WFLG BUFFER WRITTEN FLAG
	DB	00		;00 BIOS SCRATCH FLAG
	DW	0000		;TRACK BUFFER CONTENTS'
				;  PHYSICAL TRACK
	DW	0000		;SECTOR BUFFER CONTENTS'
				;  PHYSICAL SECTOR
	DW	DIRBUF		;BUFFAD BUFFER ADDRESS

        PAGE
*************************************************************
*                                                           *
LM
        db      0               ;EXM
        dw      299             ;DSM
        dw      127             ;DRM
        db      0c0h            ;AL0
        db      0               ;AL1
        dw      32              ;CKS
        dw      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        db      74h             ;16*((#cpm sectors/physical 
                                ;sector) -1) + log2(#bytes 
                                ;per sector/128) + 1 +
                                  db      0               ;AL1
        dw      64              ;CKS
        dw      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        db      1ah

        PAGE
*************************************************************
*                                                           *
* The following DPB defines a diskette as 512 byte sectors, *
* double density, and double sided.                         *
*                                                           *
*************  *
*                                                           *
*************************************************************

dpzero  dw      0               ;Address of translation table 
                                ;       (filled in by setdrv)
        dw      0,0,0,0         ;Used by BDOS
        DB      0
	DB	0		;MF  MEDIA FLAG
        dw      0               ;Address of DPB (filled in 
                                ; by setdrv)
        dw      csv0            ;Directory check vector       mov     c,a             ;C <- sector #
        call    djsec           ;Set the sector to transfer
        lxi     b,buffer        ;Set the DMA address
        call    djdma
        call    djread          ;The read operation is 
                                ;  modified to write
retryop equ     $-2
        pop     b               ;Restore the retry counter
        mvi     a,0             ;No error exit status
        rnc                     ;Return no error
        dcr     b               mov     m,a             ;Move it
        inx     d               ;Bump pointers
        inx     h
        dcr     b               ;Update counter
        jnz     movlop          ;Continue moving until done
        ret

        PAGE
*************************************************************
*                                                           *
* Terminal driver subroutines. Iobyte is not used.          *
* Note that the console device is NOT the DJ2D memory       *
* mapped serial I/****

CONOUT:                         ;WRITE A CHARACTER
        IN      03H
        ANI     01H
        JZ      CONOUT          ;WAIT TILL THE BUFFER IS 
                                ; EMPTY
        MOV     A,C             ;WRITE THE CHARACTER
        OUT     02H
        RET

*************************************************************
*                                                           *
* LEFT SERIAL PORT ROUTINES.  CONSOLE INPUT STATUS          *
*                              ***********************************************
*                                                           *
* RIGHT SERIAL PORT ROUTINES.  RIGHT OUTPUT                 *
*                                                           *
*************************************************************

RTOUT:                          ;WRITE A CHARACTER
        IN      05H
        ANI     01H
        JZ      RTOUT           ;WAIT TILL THE BUFFER IS 
                                ; EMPTY
        MOV      ;Update the retry counter
        stc                     ;Assume retry count expired
        mvi     a,0ffh          ;Error return
        rz
        jmp     retrylp         ;Try again

        PAGE
*************************************************************
*                                                           *
* Fill fills the buffer with a new sector from the disk.    *
*                                                           *
***************************************************O port. The NorthStar serial port is      *
* used instead.                                             *
*                                                           *
*************************************************************

        ;I/O ROUTINES FOR NORTHSTAR MOTHERBOARD

*************************************************************
*                                                           *
* LEFT SERIAL PORT ROUTINES.  CONSOLE I/O                   *
*                                                                *
*************************************************************

CONST:                          ;RETURN INPUT BUFFER STATUS
        IN      03H
        ANI     02H
        RZ                      ;RETURN NOT READY
        MVI     A,0FFH
        RET                     ;THERE IS A CHARACTER READY

*************************************************************
*                                                           *
* LEFT SERIAL PORT ROUTINES.  CONSOLE OUT STATUS A,C             ;WRITE THE CHARACTER
        OUT     04H
        RET

*************************************************************
*                                                           *
* RIGHT SERIAL PORT ROUTINES.  RIGHT INPUT STATUS           *
*                                                           *
*************************************************************

RTIST:                          ;RETURN INPUT BUFFER STATUS
        IN      05H
        ANI     02H
        RZ       **********

fill    call    flushA          ;Flush buffer first
        rc                      ;Check for error
        lxi     d,cpmdrv        ;Update the drive, track, 
                                ;  and sector
        lxi     h,bufdrv        
        mvi     b,3             ;Number of bytes to move
        call    movlop          ;Copy the data
        lxi     h,djread
        jmp     prep            ;Select drive, track, and 
                                ;  sector. Then read the 
                           *
*************************************************************
*************************************************************
*                                                           *
* LEFT SERIAL PORT ROUTINES.  CONSOLE INPUT                 *
*                                                           *
*************************************************************

CONIN:                          ;READ A CHARACTER
        IN      03H
        ANI     02H
        JZ              *
*                                                           *
*************************************************************

CONOST:                         ;RETURN OUTPUT BUFFER STATUS
        IN      03H
        ANI     01H
        RZ                      ;RETURN NOT READY
        MVI     A,0FFH
        RET                     ;RETURN READY

        PAGE
*************************************************************
*                                                           *
*               ;RETURN NOT READY
        MVI     A,0FFH
        RET                     ;THERE IS A CHARACTER READY

*************************************************************
*                                                           *
* RIGHT SERIAL PORT ROUTINES.  RIGHT OUT STATUS             *
*                                                           *
*************************************************************

RTOST:                          ;RETURN OUTPUT BUFFER STATUS
        IN                

*************************************************************
*                                                           *
* Mover moves 128 bytes of data. Source pointer in DE, Dest *
* pointer in HL.                                            *
*                                                           *
*************************************************************

mover   mvi     b,128           ;Length of transfer
movlop  ldax    d               ;Get a byte of source
          CONIN           ;WAIT TILL A CHARACTER IS 
                                ; READY
        IN      02H             ;GET THE CHARACTER
        ANI     7FH             ;STRIP PARITY
        RET

*************************************************************
*                                                           *
* LEFT SERIAL PORT ROUTINES.  CONSOLE OUTPUT                *
*                                                           *
********************************************************* RIGHT SERIAL PORT ROUTINES.  RIGHT INPUT                  *
*                                                           *
*************************************************************

RTIN:                           ;READ A CHARACTER
        IN      05H
        ANI     02H
        JZ      RTIN            ;WAIT TILL A CHARACTER IS 
                                ; READY
        IN      04H             ;GET THE CHARACTER
        ANI     7FH             ;STRIP PARITY
        RET

**************
        dw      alv0            ;Allocation vector
	DW	DIRBCB		;DIRECTORY BUFFER CONTROL 
				;  BLOCK
	DW	0FFFFH		;DTABCB DATA BUFFER CONTROL 
				;  BLOCK
	DW	0FFFFH		;HASH DIRECTORY HASHING TABLE
	DB	0		;HBANK BANK # OF HASH TABLE	

dpone   dw      0
        dw      0,0,0,0
        DB	0
	DB	0
        dw      0
        dw      csv1
        dw      alv1
	DW	DIRBCB
	DW	0FFFFH
	DW	0FFFFH
	DB	0

dptwo   dw      0
        dw      0,0,0,0
        DB	0
	DB	0
        dw      0
        d
buftrk  db      0               ;Track that buffer belongs to
bufsec  db      0               ;Sector that buffer belongs to

buffer  ds      1024            ;Maximum size buffer for 1K 
                                ; sector

*************************************************************
*                                                           *
*  ALLOCATION VECTORS (FOR 4 DRIVES)                        *
*  EACH VECTOR REQUIRES 2 BITS FOR EACH BLOCK ON THE DRIVE  *
*                         mov     c,a             ;Output character in C
        call    cout            ;Output the character
        pop     h         ;Test for end
        rz                      ;Return if done
        push    h               ;Save pointer to text
     e 
                                ;  message
        inx     h               ;Bump text pointer
        ana     a                 *
*************************************************************

message mov     a,m             ;Get a character of thinto *
* the buffer.                                               *
*                                                           *
*************************************************************

write   mov     a,c             ;Save write command type
        sta     writtyp
        mvi     a,1             ;Set write command
        db      (mvi) or (b*8)  ;This "mvi b" instruction  
                                ; causes the following 
                                ; "xra a" to be skipped overw      csv2
        dw      alv2
	DW	DIRBCB
	DW	0FFFFH
	DW	0FFFFH
	DB	0

dpthre  dw      0
        dw      0,0,0,0
        DB	0
	DB	0
        dw      0
        dw      csv3
        dw      alv3
	DW	DIRBCB
	DW	0FFFFH
	DW	0FFFFH
	DB	0


*************************************************************
*                                                           *
*  DIRECTORY BUFFER CONTROL BLOCK                           *
*                                                           *
*****                                     *
*************************************************************

alv0    ds      150             ;Allocation vector for drv A
alv1    ds      150             ;Allocation vector for drv B
alv2    ds      150             ;Allocation vector for drv C
alv3    ds      150             ;Allocation vector for drv D

*************************************************************
*                                                           *
*  CHECKSUM VECTORS (FOR 4 DRIV***

xlts    dw      xlt128          ;Xlt for 128 byte sectors
        dw      xlt256          ;Xlt for 256 byte sectors
        dw      xlt512          ;Xlt for 512 byte sectors
        dw      xlt124          ;Xlt for 1024 byte sectors

*************************************************************
*			                                    *
* The table following the xlt's is a table of the DPB's,    *
* used by the SETDRV subroutine to calculate density	    *
*         	                          .

*************************************************************
*                                                           *
* Read routine to buffer data from the disk. If the sector  *
* requested from CP/M is in the buffer, then the data is    *
* simply transferred from the buffer to the desired dma     *
* address. If the buffer does not contain the desired       *
* sector, the buffer is flushed to the disk if it has ever  *
* been written into, then filled with the sector from the   *
* d********************************************************

DIRBCB: DB	0FFH		;DRV  DRIVE NUMBER
	DB	00,00,00	;REC# RECORD POSITION IN
				;  BUFFER
	DB	00		;WFLG BUFFER WRITTEN FLAG
	DB	00		;00 BIOS SCRATCH FLAG
	DW	0000		;TRACK BUFFER CONTENTS'
				;  PHYSICAL TRACK
	DW	0000		;SECTOR BUFFER CONTENTS'
				;  PHYSICAL SECTOR
	DW	DIRBUF		;BUFFAD BUFFER ADDRESS

        PAGE
*************************************************************
*                                                           *
ES)                          *
*  EACH VECTOR REQUIRES 1 BIT FOR EVERY 4 DIRECTORY ENTRIES *
*                                                           *
*************************************************************

csv0    ds      64              ;Directory check vector 
                                ; drive A
csv1    ds      64              ;Directory check vector 
                                ; drive B
csv2    ds      64              ;Directory check vector 
                                               *
*************************************************************

	DW	DPB128S		; 128 BYTE SECTORS SINGLE SIDE
	DW	DPB256S		; 256 BYTE SECTORS SINGLE SIDE
	DW	DPB512S		; 512 BYTE SECTORS SINGLE SIDE
	DW	DP1024S		; 1024 BYTE SECTORS SINGLE SIDE
 	DW	DPB128D		; 128 BYTE SECTORS DOUBLE SIDE
	DW	DPB256D		; 256 BYTE SECTORS DOUBLE SIDE
	DW	DPB512D		; 512 BYTE SECTORS DOUBLE SIDE
	DW	DP1024D		; 1024 BYTE SECTORS DOUBLE SIDE

        PAGE
***********************************************isk that contains the desired CP/M sector.               *
*                                                           *
*************************************************************

read    xra     a               ;Set the command type to read
        sta     rdwr            ;Save command type

        PAGE
*************************************************************
*                                                           *
* Redwrt calculates the physical sector on the disk that    *
* co
* Cbios ram locations that don't need initialization.       *
*                                                           *
*************************************************************

cpmsec  db      0               ;CP/M sector #
cpmdrv  db      0               ;CP/M drive #
cpmtrk  db      0               ;CP/M track #
truesec db      0               ;Disk Jockey sector that 
                                ; contains CP/M sector

bufdrv  db      0               ;Drive that buffer belongs to   ; drive C
csv3    ds      64              ;Directory check vector 
                                ; drive D
*************************************************************
*                                                           *
*   DIRECTORY BUFFER                                        *
*                                                           *
*************************************************************

dirbuf  ds      128             ;Directory buffer
;
        end
**************
*                                                           *
* Write routine moves data from memory into the buffer. If  *
* the desired CP/M sector is not contained in the disk      *
* buffer, the buffer is first flushed to the disk if it has *
* ever been written into, then a read is performed into the *
* buffer to get the desired sector. Once the correct sector *
* is in memory, the buffer written indicator is set, so the *
* buffer will be flushed, then the data is transferred ***********************************************
*                                                           *
* RIGHT SERIAL PORT ROUTINES.  RIGHT OUTPUT                 *
*                                                           *
*************************************************************

RTOUT:                          ;WRITE A CHARACTER
        IN      05H
        ANI     01H
        JZ      RTOUT           ;WAIT TILL THE BUFFER IS 
                                ; EMPTY
        MOV         ;READ A CHARACTER
        IN      06H
        ANI     01H
        JZ      PARIN           ;WAIT TILL A CHARACTER IS 
                                ; READY
        IN      00H             ;GET THE CHARACTER
        PUSH    PSW
        MVI     A,30H           ;RESET THE PARALLEL INPUT 
                                ; FLAG
        OUT     06H
        POP     PSW
        ANI     7FH             ;STRIP PARITY
        RET

*************************************************************
*    TUS               *
*                                                           *
*************************************************************

LISTST:                         ;RETURN OUTPUT BUFFER STATUS
        IN      06H
        ANI     02H
        RZ                      ;RETURN NOT READY
        MVI     A,0FFH
        RET                     ;RETURN READY

        PAGE  
*************************************************************
*                                                       2,53,54,55,56
        db      9,10,11,12,13,14,15,16
        db      33,34,35,36,37,38,39,40
        db      57,58,59,60,61,62,63,64
        db      17,18,19,20,21,22,23,24
        db      41,42,43,44,45,46,47,48

        PAGE
*************************************************************
*                                                           *
* Each of the following tables describes a diskette with    *
* the specified characteristics. The tables are currently   *
* stored on track 0 secto A,C             ;WRITE THE CHARACTER
        OUT     04H
        RET

*************************************************************
*                                                           *
* RIGHT SERIAL PORT ROUTINES.  RIGHT INPUT STATUS           *
*                                                           *
*************************************************************

RTIST:                          ;RETURN INPUT BUFFER STATUS
        IN      05H
        ANI     02H
        RZ                                                              *
* PARALLEL PORT ROUTINES.  PRINTER OUTPUT                   *
*                                                           *
*************************************************************

LIST:                           ;WRITE A CHARACTER
        IN      06H
        ANI     02H
        JZ      LIST            ;WAIT TILL THE BUFFER IS 
                                ; EMPTY
        MVI     A,20H           ;RESET THE PARALLEL OUTPUT 
            *
* Xlt tables (sector skew tables) for CP/M 2.0. These       *
* tables define the sector translation that occurs when     *
* mapping CP/M sectors to physical sectors on the disk.     *
* There is one skew table for each of the possible sector   *
* sizes. Currently the tables are located on track 0        *
* sectors 6 and 8. They are loaded into memory in the Cbios *
* ram by the cold boot routine.                             *
*                                                           *
*r 13. They are read into memory by *
* the GOCPM routine in the CBIOS for CP/M ver 2.2.          *
*                                                           *
*************************************************************
*************************************************************
*                                                           *
* The following DPB defines a  diskette for 128 byte        *
* sectors, single density, and single sided.                *
*                                               ;RETURN NOT READY
        MVI     A,0FFH
        RET                     ;THERE IS A CHARACTER READY

*************************************************************
*                                                           *
* RIGHT SERIAL PORT ROUTINES.  RIGHT OUT STATUS             *
*                                                           *
*************************************************************

RTOST:                          ;RETURN OUTPUT BUFFER STATUS
        IN                          ; FLAG
        OUT     06H
        MOV     A,C             ;WRITE THE CHARACTER, STROBE 
                                ; BIT 7
NSPOUT: ORI     80H
        OUT     00H
        ANI     7FH
        OUT     00H
        ORI     80H
        OUT     00H
        RET

*************************************************************
*                                                           *
* PARALLEL PORT ROUTINES.   INPUT STATUS                    *
*                        ************************************************************

xlt128  db      0
        db      1,7,13,19,25
        db      5,11,17,23
        db      3,9,15,21
        db      2,8,14,20,26
        db      6,12,18,24
        db      4,10,16,22

xlt256  db      0
        db      1,2,19,20,37,38
        db      3,4,21,22,39,40
        db      5,6,23,24,41,42
        db      7,8,25,26,43,44
        db      9,10,27,28,45,46
        db      11,12,29,30,47,48
        db      13,14,31,32,49,50
                            *
*************************************************************

dpb128s dw      26              ;SPT CP/M sectors/track
        db      3               ;BSH BLOCK SHIFT FACTOR
        db      7               ;BLM BLOCK MASK
        db      0               ;EXM EXTENT MASK
        dw      242             ;DSM DISK SPACE MAXIMUM
        dw      63              ;DRM DIRECTORY MAXIMUM
        db      0c0h            ;AL0 INITIAL ALLOTARION
        db      0               ;A    05H
        ANI     01H
        RZ                      ;RETURN NOT READY
        MVI     A,0FFH
        RET                     ;RETURN READY

        PAGE
*************************************************************
*                                                           *
* PARALLEL PORT ROUTINES.  PARALLEL INPUT                   *
*                                                           *
*************************************************************

PARIN:                                                        *
*************************************************************

PINPST:                         ;RETURN INPUT BUFFER STATUS
        IN      06H
        ANI     01H
        RZ                      ;RETURN NOT READY
        MVI     A,0FFH
        RET                     ;RETURN READY

        PAGE
*************************************************************
*                                                           *
* PARALLEL PORT ROUTINES.  LIST DEVICE STA       db      15,16,33,34,51,52
        db      17,18,35,36

xlt512  db      0
        db      1,2,3,4,17,18,19,20
        db      33,34,35,36,49,50,51,52
        db      5,6,7,8,21,22,23,24
        db      37,38,39,40,53,54,55,56
        db      9,10,11,12,25,26,27,28
        db      41,42,43,44,57,58,59,60
        db      13,14,15,16,29,30,31,32
        db      45,46,47,48

xlt124  db      0
        db      1,2,3,4,5,6,7,8
        db      25,26,27,28,29,30,31,32
        db      49,50,51,5    c,a             ;Make new sector the requested 
                                ;  sector
        pop     d
        call    sideone
        mvi     a,80h           ;Side two bit
        ora     l               ;       and sector
        mov     l,a
        ret

        PAGE    
*************************************************************
*                                                           *
* Setdrv selects the next drive to be used in read/write    *
* operations. If the drive has    ;Table of XLT addresses
	PUSH	H
        mov     e,a
        mvi     d,0
        dad     d
        push    h               ;Save pointer to proper XLT
        call    getdpb          ;Get DPH pointer into DE
        xchg                    ;
        pop     d
        mvi     b,2             ;Number of bytes to move
        call    movlop          ;Move the address of XLT
        lxi     d,10            ;Offset to DPB pointer
        dad     d               ;HL <- &DPH.DPB
        XCHG
	POP	B address
        inx     h
        mov     h,m             ;Get low byte of DPB
        mov     l,a
        pop     d
        ret

*************************************************************
*                                                           *
* Xlts is a table of address that point to each of the xlt  *
* tables for each sector size.                              *
*                                                           *
********************************************************** operation
        jnz     into            ;Transfer data into the buffer
outof   call    mover
        xra     a
        ret

into    xchg                    ;
        call    mover           ;Move the data, HL = destination
                                ;       DE = source
        mvi     a,1
        sta     bufwrtn         ;Set buffer written into flag
        mvi     a,0             ;Check for directory write
writtyp equ     $-1
        dcr     a
        mvi     a,0
        sta     writ never been selected before,  *
* a parameter table is created which correctly describes    *
* the diskette currently in the drive. Diskettes can be of  *
* four different sector sizes:                              *
*       1) 128 bytes single density.                        *
*       2) 256 bytes double density.                        *
*       3) 512 bytes double density.                        *
*       4) 1024 bytes double density.                       *
*                                     H
        pop     psw             ;Offset to correct DPB
        mov     c,a
        mvi     b,0
        dad     b		;ADD TO TRANSLATE TABLE
				; TO POINT TO DENSITY
				; (THE DPB TABLE IS CLEVERLY 
				; LOCATED RIGHT AFTER THE
				; XLT TABLE)
        xchg                    ;Put DPB address in DPH
	MVI	B,2		;MOVE DPB ADDRESS INTO DPH
	CALL	MOVLOP
setdrv1 call    getdpb          ;Get address of DPB in HL
        lxi     b,17            ;Offset to sector size
        dad     b
        mov  drv D

*************************************************************
*                                                           *
*  CHECKSUM VECTORS (FOR 4 DRIVES)                          *
*  EACH VECTOR REQUIRES 1 BIT FOR EVERY 4 DIRECTORY ENTRIES *
*                                                           *
*************************************************************

csv0    ds      64              ;Directory check vector 
                                ; drive A
csv1    ds      64    typ         ;Set no directory write
        rnz                     ;No error exit

*************************************************************
*                                                           *
* FlushA writes the contents of the buffer out to the disk  *
* if it has ever been written into.                         *
*                                                           *
*************************************************************

flushA  mvi     a,0             ;The 0 is mod                      *
*************************************************************

setdrv  mov     a,c             ;Save the drive #
        sta     cpmdrv
        cpi     maxdisk         ;Check for a valid drive #
        jnc     zret            ;Illegal drive #
        mov     a,e             ;Test if drive ever logged 
                                ;  in before
        ani     1
        jnz     setdrv1         ;Bit 0 of E = 0 -> Never 
                                ;  selected before
   a,m             ;Get sector size
        ani     7h
        sta     secsiz
        mov     a,m
        rar
        rar
        rar
        rar
        ani     0fh
        sta     secpsec
        xchg                    ;HL <- DPH
        ret

zret    lxi     h,0             ;Seldrv error exit
        ret

        PAGE
*************************************************************
*                                                           *
* Getdpb returns HL pointing to the DPB of the          ;Directory check vector 
                                ; drive B
csv2    ds      64              ;Directory check vector 
                                ; drive C
csv3    ds      64              ;Directory check vector 
                                ; drive D
*************************************************************
*                                                           *
*   DIRECTORY BUFFER                                        *
*                                         ified to reflect
                                ;  if the buffer has been 
                                ;  written into
bufwrtn equ     $-1
        ana     a               ;Test if written into
        rz                      ;Not written, all done
        lxi     h,djwrite       ;Write operation

*************************************************************
*                                                           *
* Prep prepares to read/write the disk. Retries are         *
* attempted.        mvi     a,1             ;Select sector 1 of track 1
        sta     truesec
        sta     cpmtrk
        call    fill            ;Flush buffer and refill
        jc      zret            ;Test for error return
        call    djstat          ;Get status on current drive
        ani     2ch             ;LOK AT SIDE AND DENSITY BITS
	MOV	E,A
	ANI	20H
	MOV	A,E
	JNZ	SETDR1
	ORI	10H
SETDR1:	RAR
        push    psw             ;SAVE DJSTAT 1/2 SIDED INFO
	ANI	6
        lxi     h,xlts       currently    *
* selected drive, DE pointing to DPH.                       *
*                                                           *
*************************************************************

getdpb  lda     cpmdrv          ;Get drive #
	LXI	H,DPZERO
	LXI	D,19H
GETDP1:	ORA	A
	JZ	GETDP2
	DAD	D
	DCR	A
	JMP	GETDP1
;
GETDP2: push    h               ;Save address of DPH
        lxi     d,12            ;Offset to DPB
        dad     d
        mov     a,m             ;Get low byte of DP                  *
*************************************************************

dirbuf  ds      128             ;Directory buffer
;
        end
   $-2
        mvi     a,0             ;The zero gets modified to 
                                ;  contain a zero if a read, 
                                ;  or a 1 if write
rdwr    equ     $-1
        ana     a               ;Test which kind of;THERE IS A CHARACTER READY

        PAGE  
*************************************************************
*                                                           *
* Xlt tables (sector skew tables) for CP/M 2.0. These       *
* tables define the sector translation that occurs when     *
* mapping CP/M sectors to physical sectors on the disk.     *
* There is one skew table for each of the possible sector   *
* sizes. Currently the tables are located on track 0        *
* sectors 6 and 8. They             *
* Each of the following tables describes a diskette with    *
* the specified characteristics. The tables are currently   *
* stored on track 0 sector 13. They are read into memory by *
* the GOCPM routine in the CBIOS for CP/M ver 2.2.          *
*                                                           *
*************************************************************
*************************************************************
*                                                          52              ;CP/M sectors/track
        db      4               ;BSH
        db      15              ;BLM
        db      0               ;EXM
        dw      242             ;DSM
        dw      127             ;DRM
        db      0c0h            ;AL0
        db      0               ;AL1
        dw      32              ;CKS
        dw      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        db      12h             ;16*((#cpm sectors/physical 
                                ;*************************************

dp1024s dw      64              ;CP/M sectors/track
        db      4               ;BSH
        db      15              ;BLM
        db      0               ;EXM
        dw      299             ;DSM
        dw      127             ;DRM
        db      0c0h            ;AL0
        db      0               ;AL1
        dw      32              ;CKS
        dw      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        db      74h             ;16*((#cpare loaded into memory in the Cbios *
* ram by the cold boot routine.                             *
*                                                           *
*************************************************************

xlt128  db      0
        db      1,7,13,19,25
        db      5,11,17,23
        db      3,9,15,21
        db      2,8,14,20,26
        db      6,12,18,24
        db      4,10,16,22

xlt256  db      0
        db      1,2,19,20,37,38
        db      3,4,21,22,39,40
         *
* The following DPB defines a  diskette for 128 byte        *
* sectors, single density, and single sided.                *
*                                                           *
*************************************************************

dpb128s dw      26              ;SPT CP/M sectors/track
        db      3               ;BSH BLOCK SHIFT FACTOR
        db      7               ;BLM BLOCK MASK
        db      0               ;EXM EXTENT MASK
        dw      242             ;DSM Dsector) -1) + log2(#bytes 
                                ;per sector/128) + 1 + 8 
                                ;if double sided.
        PAGE
*************************************************************
*                                                           *
* The following DPB defines a diskette as 512 byte sectors, *
* double density, and single sided.                         *
*                                                           *
*********************************************m sectors/physical 
                                ;sector) -1) + log2(#bytes 
                                ;per sector/128) + 1 +
                                ;8 if double sided.

        PAGE
*************************************************************
*                                                           *
* The following DPB defines a diskette for 128 byte sectors,*
* single density, and double sided.                         *
*                                                       db      5,6,23,24,41,42
        db      7,8,25,26,43,44
        db      9,10,27,28,45,46
        db      11,12,29,30,47,48
        db      13,14,31,32,49,50
        db      15,16,33,34,51,52
        db      17,18,35,36

xlt512  db      0
        db      1,2,3,4,17,18,19,20
        db      33,34,35,36,49,50,51,52
        db      5,6,7,8,21,22,23,24
        db      37,38,39,40,53,54,55,56
        db      9,10,11,12,25,26,27,28
        db      41,42,43,44,57,58,59,60
        db      13,14,15,ISK SPACE MAXIMUM
        dw      63              ;DRM DIRECTORY MAXIMUM
        db      0c0h            ;AL0 INITIAL ALLOTARION
        db      0               ;AL1   VECTORS
        dw      16              ;CKS DIRECTORY CHECK SIZE
        dw      2               ;OFF TRACK OFFSET
	DB	00		;PSH PHYSICAL REC SHIFT FACT
	DB	00		;PHM PHYSICAL RECORD MASK
				;NEXT BYTE USED BY THE BIOS
        db      1h              ;16*((#cpm sectors/physical 
                                ;sector) -1) + log2(#b****************

dpb512s dw      60              ;CP/M sectors/track
        db      4               ;BSH
        db      15              ;BLM
        db      0               ;EXM
        dw      280             ;DSM
        dw      127             ;DRM
        db      0c0h            ;AL0
        db      0               ;AL1
        dw      32              ;CKS
        dw      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        db      33h             ;16*((#cpm sectors/physical 
       *
*************************************************************

dpb128d dw      52              ;CP/M sectors/track
        db      4               ;BSH
        db      15              ;BLM
        db      1               ;EXM
        dw      242             ;DSM
        dw      127             ;DRM
        db      0c0h            ;AL0
        db      0               ;AL1
        dw      32              ;CKS
        dw      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
       16,29,30,31,32
        db      45,46,47,48

xlt124  db      0
        db      1,2,3,4,5,6,7,8
        db      25,26,27,28,29,30,31,32
        db      49,50,51,52,53,54,55,56
        db      9,10,11,12,13,14,15,16
        db      33,34,35,36,37,38,39,40
        db      57,58,59,60,61,62,63,64
        db      17,18,19,20,21,22,23,24
        db      41,42,43,44,45,46,47,48

        PAGE
*************************************************************
*                                               ytes 
                                ;per sector/128) + 1 + 8 if 
                                ;double sided.

*************************************************************
*                                                           *
* The following DPB defines a diskette for 256 byte         *
* sectors, double density, and single sided.                *
*                                                           *
*************************************************************

dpb256s dw                                   ;sector) -1) + log2(#bytes 
                                ;per sector/128) + 1 + 8 
                                ;if double sided.

*************************************************************
*                                                           *
* The following DPB defines a diskette as 1024 byte sectors,*
* double density, and single sided.                         *
*                                                           *
***********************************************
*                                                           *
* Settrk saves the track # to seek to. Nothing is done at   *
* this point, everything is deffered until a read or write. *
*                                                           *
*************************************************************

settrk  mov     a,c             ;A <- track #
        sta     cpmtrk          ;CP/M track #
        ret

        PAGE
***********************************************    ;8 IF DOUBLE SIDED.

        PAGE
*************************************************************
*                                                           *
* THE FOLLOWING DPB DEFINES A DISKETTE FOR 128 BYTE SECTORS,*
* SINGLE DENSITY, AND DOUBLE SIDED.                         *
*                                                           *
*************************************************************

DPB128D DW      52              ;CP/M SECTORS/TRACK
        DB      4               ;BSH
************************************************

DPB512D DW      120             ;CP/M SECTORS/TRACK
        DB      4               ;BSH
        DB      15              ;BLM
        DB      0               ;EXM
        DW      561             ;DSM
        DW      255             ;DRM
        DB      0F0H            ;AL0
        DB      0               ;AL1
        DW      64              ;CKS
        DW      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        DB      3BH

*******
        DW      ALV0            ;ALLOCATION VECTOR
	DW	DIRBCB		;DIRECTORY BUFFER CONTROL 
				;  BLOCK
	DW	0FFFFH		;DTABCB DATA BUFFER CONTROL 
				;  BLOCK
	DW	0FFFFH		;HASH DIRECTORY HASHING TABLE
	DB	0		;HBANK BANK # OF HASH TABLE	

DPONE   DW      0
        DW      0,0,0,0
        DB	0
	DB	0
        DW      0
        DW      CSV1
        DW      ALV1
	DW	DIRBCB
	DW	0FFFFH
	DW	0FFFFH
	DB	0

DPTWO   DW      0
        DW      0,0,0,0
        DB	0
	DB	0
        DW      0
        D               ;EXM
        DW      280             ;DSM
        DW      127             ;DRM
        DB      0C0H            ;AL0
        DB      0               ;AL1
        DW      32              ;CKS
        DW      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        DB      33H             ;16*((#CPM SECTORS/PHYSICAL 
                                ;SECTOR) -1) + LOG2(#BYTES 
                                ;PER SECTOR/128) + 1 + 8 
                                ;IF DOUBLE SID        DB      15              ;BLM
        DB      1               ;EXM
        DW      242             ;DSM
        DW      127             ;DRM
        DB      0C0H            ;AL0
        DB      0               ;AL1
        DW      32              ;CKS
        DW      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        DB      9H

*************************************************************
*                                                           *
* THE FOLLOWING DPB DEFIN******************************************************
*                                                           *
* THE FOLLOWING DPB DEFINES A DISKETTE AS 1024 BYTE SECTORS,*
* DOUBLE DENSITY, AND DOUBLE SIDED.                         *
*                                                           *
*************************************************************

DP1024D DW      128             ;CP/M SECTORS/TRACK
        DB      4               ;BSH
        DB      15              ;BLM
        DBW      CSV2
        DW      ALV2
	DW	DIRBCB
	DW	0FFFFH
	DW	0FFFFH
	DB	0

DPTHRE  DW      0
        DW      0,0,0,0
        DB	0
	DB	0
        DW      0
        DW      CSV3
        DW      ALV3
	DW	DIRBCB
	DW	0FFFFH
	DW	0FFFFH
	DB	0


*************************************************************
*                                                           *
*  DIRECTORY BUFFER CONTROL BLOCK                           *
*                                                           *
*****ED.

*************************************************************
*                                                           *
* THE FOLLOWING DPB DEFINES A DISKETTE AS 1024 BYTE SECTORS,*
* DOUBLE DENSITY, AND SINGLE SIDED.                         *
*                                                           *
*************************************************************

DP1024S DW      64              ;CP/M SECTORS/TRACK
        DB      4               ;BSH
        DB      15              ;BES A DISKETTE AS 256 BYTE SECTORS, *
* DOUBLE DENSITY, AND DOUBLE SIDED.                         *
*                                                           *
*************************************************************

DPB256D DW      104             ;CP/M SECTORS/TRACK
        DB      4               ;BSH
        DB      15              ;BLM
        DB      0               ;EXM
        DW      486             ;DSM
        DW      255             ;DRM
        DB      0F0H            ;AL0
        0               ;EXM
        DW      599             ;DSM
        DW      255             ;DRM
        DB      0F0H            ;AL0
        DB      0               ;AL1
        DW      64              ;CKS
        DW      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        DB      7CH

        PAGE
*************************************************************
*                                                           *
* CP/M DISK PARAMETER HEADERS, (FOR 4 DRIVES)             ********************************************************

DIRBCB: DB	0FFH		;DRV  DRIVE NUMBER
	DB	00,00,00	;REC# RECORD POSITION IN
				;  BUFFER
	DB	00		;WFLG BUFFER WRITTEN FLAG
	DB	00		;00 BIOS SCRATCH FLAG
	DW	0000		;TRACK BUFFER CONTENTS'
				;  PHYSICAL TRACK
	DW	0000		;SECTOR BUFFER CONTENTS'
				;  PHYSICAL SECTOR
	DW	DIRBUF		;BUFFAD BUFFER ADDRESS

        PAGE
*************************************************************
*                                                           *
LM
        DB      0               ;EXM
        DW      299             ;DSM
        DW      127             ;DRM
        DB      0C0H            ;AL0
        DB      0               ;AL1
        DW      32              ;CKS
        DW      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        DB      74H             ;16*((#CPM SECTORS/PHYSICAL 
                                ;SECTOR) -1) + LOG2(#BYTES 
                                ;PER SECTOR/128) + 1 +
                                  DB      0               ;AL1
        DW      64              ;CKS
        DW      2               ;OFF
	DB	00		;PSH
	DB	00		;PHM
				;
        DB      1AH

        PAGE
*************************************************************
*                                                           *
* THE FOLLOWING DPB DEFINES A DISKETTE AS 512 BYTE SECTORS, *
* DOUBLE DENSITY, AND DOUBLE SIDED.                         *
*                                                           *
*************  *
*                                                           *
*************************************************************

DPZERO  DW      0               ;ADDRESS OF TRANSLATION TABLE 
                                ;       (FILLED IN BY SETDRV)
        DW      0,0,0,0         ;USED BY BDOS
        DB      0
	DB	0		;MF  MEDIA FLAG
        DW      0               ;ADDRESS OF DPB (FILLED IN 
                                ; BY SETDRV)
        DW      CSV0            ;DIRECTORY CHECK VECTOR*****************************
*			                                    *
* To install this BIOS into CP/M 3.0, perform the following *
* steps:			                            *
*	1. Add your own console and printer I/O to this file*
*	   at CONIN:, CONOUT:, CONST:, LIST:, and LISTST:   *
*	2. Add any initialization that you need at TINIT:   *
*	3. Set the LDRBIOS equate in this file to TRUE	    *	
*	4. RMAC SCB 	(ASSEMBLE SCB.ASM, supplied)	    *
*	5. RMAC BIOS3 	(ASSEMble LDRBIOS)		    *
*	6. REN L****************************

ORIGIN	EQU	0E000H		;EPROM ORIgin of your DJ2D board
DJRAM	EQU	ORIGIN+400H	;RAM address
DJHOME	EQU	DJRAM+9H	;DJ2D track zero seek
DJTRK	EQU	DJRAM+0CH	;DJ2D track seek routine
DJSEC	EQU	DJRAM+0FH	;DJ2D set sector routine
DJDMA	EQU	DJRAM+012H	;SEt DMA address
DJREAD	EQU	DJRAM+15H	;REad routine
DJWRITE	EQU	DJRAM+18H	;Write routine
DJSEL	EQU	DJRAM+1BH	;DJ2D select drive routine
DJSTAT	EQU	DJRAM+27H	;STatus routine
DJSIDE	EQU	DJRAM+30H	;SEt side routine



***********                 *
*  THE BIOS JUMP TABLE			                    *
*			                                    *
* The jump table below must remain in the same order, the   *
* routines may be changed, but the function executed must be*
* the same.  There are 33 jumps in the CP/M Plus BIOS vector*
*			                                    *
*************************************************************
;
?BOOT:	JMP	CBOOT		;cOLD STArt entry point
WBOOTE:
?WBOOT:	JMP	WBOOT		;WARM STart entry point
?CONST:	JMP	RESERV2		;RESERVED FOr CP/M Plus

;
;  Device Table is not implemented, so return HL=0
DEVTBL:	LXI	H,0
	RET
;
;  Flush routine is not implemented, so return A=0
FLUSH:	XRA	A
	RET
;
;  Drive Table is not used, so return HL=0FFFEH
DRVTBL:	LXI	H,0FFFEH
	RET
;
;  The following jumps from the BIOS jump vector 
;    are not implemented:
AUXIST:
AUXOUT:
AUXIN:
AUXOST:
DEVINI:
MULTIO:
XMOVE:
SELMEM:
SETBNK:
RESERV1:
RESERV2:
?TIME:
	RET

******************************************DRBIOS.REL=BIOS3.REL		            *
*	7. Set the LDRBIOS equate in this file FALSE	    *	
*	8. RMAC BIOS3 (assemble BIOS)		            *
*	9. LINK BIOS3[B]=BIOS3,SCB		            *
*      10. GENCPM			                    *
*	    (Answer all questions with a carriage return    *
*	    EXCEPT ANSswer "N" at "Bank switched memory?"   *
*	    Question, and answer with your top page of	    *
*	    MEMORY WHen asked "Top page of memory?")	    *
*      11. LINK CPMLDR[L100]=CPMLDR,LDRBIOS		    *	
*      **************************************************
*			                                    *
* Miscellaneous internal BIOS equates.			    *
* We've tried to maintain compatibility with the Morrow's   *
* DJ2D BIOS.				                    *
*			                                    *
*************************************************************

LDRBIOS	EQU	FALSE	;TRUE IF YOU want to assemble as Loader BIOS
UD2	EQU	FALSE	;TRUE if want to use User/Drive byte @ addr 4
CDISK	EQU	4	;Address of last logge	JMP	CONST		;CONSOLE status A=ff=ready
?CONIN:	JMP	CONIN		;CONSOLE input  data in A
COUT:
?CONO:	JMP	CONOUT		;CONSOLE output data in C
?LIST:	JMP	LIST		;LIST DEVice    data in C
?AUXO:	JMP	AUXOUT		;PUNCH Device   none
?AUXI:	JMP	AUXIN	 	; reader device  none
?HOME	JMP	HOME		;SEEK HOME track
?SLDSK:	JMP	SETDRV		;SELECT disk    disk in C
?STTRK:	JMP	SETTRK		;SEEK Track     track in BC
?STSEC:	JMP	SETSEC		;SET SEctor     sector in BC
?STDMA:	JMP	SETDMA		;SET DMa        dma in BC
?READ:	JMP	READ		;R*******************
*			                                    *
* Cold-boot sign-on message			            *
*			                                    *
*************************************************************

PROMPT:
	IF	LDRBIOS
	DB	ACR,ALF,ALF
	DB	'Loader for Morrow Designs DJ2D Controller.'
	DB	ACR,ALF,0
	ENDIF
;
	IF	NOT LDRBIOS
	DB	ACR,ALF,ALF
	DB	'CP/M 3.0 (V'		;CP/M VERsion number
	DB	CPMREV/10+'0'
	DB	'.'
	DB	(CPMREV MOD 10)+'0'
	DB	'), BIOS rev '
	DB	REVNUM/10+'0','.'	;revision 