;NEWRLEE.ASM VERSION OF 10 NOV 94 ************************************************************* * * * Cbios for CP/M Ver 2.2 for Disk Jockey 2D controller (all * * revs). Handles diskettes with sector sizes of 128 bytes * * single density, 256, 512, 1024 bytes double density. * * * * Written by Bobby Dale Gifford. * * 9/1/79 * * * * Disk Map of sectors used by Cold Boot, Warm Boot, * * Firmware,and CP/M: * * * * trk 0 sec 1 = First sector of cold boot. e700h * * 0 2 = Cold boot 256. 80h * * 0 3 = Cold boot 512. 80h * * 0 4 = Cold boot 1024. 80h * * 0 5 = Warm boot 256. 80h * * 0 6 = Warm boot 512. 80h * * 0 7 = Warm boot 1024. 80h * * 0 8 = Cold/Warm boot. 3200h * * 0 9 = Firmware. e400h * * 0 10 = Firmware+80h. e480h * * 0 11 = Firmware+100h e500h * * 0 12 = Firmware+180h. e580h * * 0 13 = Firmware+200h. e600h * * 0 14 = Firmware+280h. e680h * * 0 15 = Firmware+300h. e700h * * 0 16 = Firmware+380h. e780h * * 0 17 = CCP. 2d00h * * 0 10 = CCP+80h. 2d80h * * 0 12 = CCP+100h. 2e00h * * 0 14 = CCP+180h. 2e80h * * 0 16 = CCP+200h. 2f00h * * 0 18 = CCP+280h. 2f80h * * 0 20 = CCP+300h. 3000h * * 0 22 = CCP+380h. 3080h * * 0 24 = CCP+400h. 3100h * * 0 26 = CCP+480h. 3180h * * 1 = Rest of CP/M. 3200h-4fffh * * * ************************************************************* TITLE 'CBIOS FOR RLEEs SYSTEM: 10 NOV 94.' ************************************************************* * * * The following revision number is in reference to the CP/M * * 2.0 Cbios. * * * ************************************************************* revnum equ 31 ;Cbios revision number cpmrev equ 22 ;CP/M revision number PAGE ************************************************************* * * * The following equates relate the Thinker Toys 2D con- * * troller. If the controller is non standard (0E000H) only * * the ORIGIN equate need be changed. This version of the * * Cbios will work with 2D controller boards rev 0, 1, 3, * * 3.1, 4. * * * ************************************************************* origin equ 0E000H djram equ origin+400h ;Disk Jockey 2D RAM address djcin equ djram+3h ;Disk Jockey 2D character ; input routine djcout equ djram+6h ;Disk Jockey 2D character ;output routine djhome equ djram+9h ;Disk Jockey 2D track zero ;seek djtrk equ djram+0ch ;Disk Jockey 2D track seek ;routine djsec equ djram+0fh ;Disk Jockey 2D set sector ;routine djdma equ djram+012h ;Disk Jockey 2D set DMA ;address djread equ djram+15h ;Disk Jockey 2D read ;routine djwrite equ djram+18h ;Disk Jockey 2D write ;routine djsel equ djram+1bh ;Disk Jockey 2D select ;drive routine djtstat equ djram+21h ;Disk Jockey 2D terminal ;status routine djstat equ djram+27h ;Disk Jockey 2D status ;routine djerr equ djram+2ah ;Disk Jockey 2D error, ;flash led djden equ djram+2dh ;Disk Jockey 2D set density ;routine djside equ djram+30h ;Disk Jockey 2D set side ;routine PAGE ************************************************************* * * * CP/M system equates. If reconfiguration of the CP/M system* * is being done, the changes can be made to the following * * equates. * * * ************************************************************* msize equ 56 ;Memory size of target CP/M bias equ (msize-20)*1024 ;Memory offset from ; 20K system ccp equ 2d00h+bias ;Console command processor bdos equ ccp+800h ;BDOS address bios equ ccp+1600h ;CBIOS address cdisk equ 4 ;Address of last logged disk buff equ 80h ;Default buffer address tpa equ 100h ;Transient memory intioby equ 0 ;Initial IOBYTE iobyte equ 3 ;IOBYTE location wbot equ 0 ;Warm boot jump address entry equ 5 ;BDOS entry jump address ************************************************************* * * * The following are internal Cbios equates. Most are misc. * * constants. * * * ************************************************************* retries equ 10 ;Max retries on disk i/o ; before error acr equ 0dh ;A carriage return alf equ 0ah ;A line feed aetx equ 3 ;A ETX char aack equ 6 ;A ACK char clear equ 1ah ;Clear screen char on ; Adm3 terminal maxdisk equ 4 ;Maximum # of disk drives dblsid equ 8 ;Side bit from controller escape equ 1bh ;Escape character eot equ 04h ;End of text character form equ 0ch ;Form feed character PAGE ************************************************************* * * * The jump table below must remain in the same order, the * * routines may be changed, but the function executed must * * be the same. * * * ************************************************************* org bios ;CBIOS starting address jmp cboot ;Cold boot entry point wboote jmp wboot ;Warm boot entry point jmp CONIST ;Console status routine jmp CONIN ;Console input cout jmp CONOUT ;Console output jmp LSTOUT ;List device output jmp PUNOUT ;Punch device output jmp RDRIN ;Reader device input jmp home ;Home drive jmp setdrv ;Select disk jmp settrk ;Set track jmp setsec ;Set sector jmp setdma ;Set DMA address jmp read ;Read the disk jmp write ;Write the disk jmp LSTOST ;List device status jmp sectran ;Sector translation djdrv jmp djsel ;Hook for SINGLE.COM program ************************************************************* * * * Signon message output during cold boot. * * * ************************************************************* prompt db acr,alf,alf db acr,alf db 'CCPZ V4.1 CP/M V2.2 ' db acr,alf db 'NorthStar/Morrow DJ-2D ' db acr,alf db 'Version of 8 Nov 94 ' db acr,alf,0 PAGE ************************************************************* * * * Utility routine to output the message pointed at by H&L, * * terminated with a null. * * * ************************************************************* message mov a,m ;Get a character of the ; message inx h ;Bump text pointer ana a ;Test for end rz ;Return if done push h ;Save pointer to text mov c,a ;Output character in C call cout ;Output the character pop h ;Restore the pointer jmp message ;Continue until null reached PAGE ************************************************************* * * * Cboot is the cold boot loader. All of CP/M has been * * loaded in when control is passed here. * * * ************************************************************* cboot lxi sp,tpa ;Set up stack call tinit ;Initialize the terminal lxi h,prompt ;Prep for sending signon msg call message ;Send the prompt xra a ;Select disk A sta cpmdrv sta cdisk ************************************************************* * * * Gocpm is the entry point from cold boots, and warm boots. * * It initializes some of the locations in page 0, and sets * * up the initial DMA address (80h). * * * ************************************************************* gocpm lxi h,buff ;Set up initial DMA address call setdma mvi a,(jmp) ;Initialize jump to warm boot sta wbot sta entry ;Initialize jump to BDOS lxi h,wboote ;Address in warm boot jump shld wbot+1 lxi h,bdos+6 ;Address in BDOS jump shld entry+1 xra a ;A <- 0 sta bufsec ;Disk Jockey buffer empty sta bufwrtn ;Set buffer not dirty flag lda cdisk ;Jump to CP/M with currently mov c,a ; selected disk in C lxi d,cmndbeg ;Beginning of initial command lxi h,ccp+8 ;Command buffer mvi a,cmndend-cmndbeg+1 ;Length of command sta ccp+7 mov b,a call movlop lda cwflg ana a lda autoflg jz cldbot rar cldbot rar jc ccp jmp ccp+3 ;Enter CP/M cwflg db 0 ;Cold/warm boot flag PAGE ************************************************************* * * * The following byte determines if an initial command is to * * be given to CP/M on warm or cold boots. The value of the * * byte is used to give the command to CP/M: * * * * 0 = never give command. * * 1 = give command on cold boots only. * * 2 = give the command on warm boots only. * * 3 = give the command on warm and cold boots. * * * ************************************************************* autoflg db 1 ;Auto command feature ************************************************************* * * * If there is a command inserted here, it will be given if * * the auto feature is enabled. * * For Example: * * * * cmndbeg db 'MBASIC MYPROG' * * cmndend db 0 * * * * will execute microsoft basic, and mbasic will execute the * * "MYPROG" basic program. * * * ************************************************************* cmndbeg db 'DUMMYARG ANOTHER1' ;For direct ; replacement. cmndend db 0 PAGE ************************************************************* * * * Wboot loads in all of CP/M except the CBIOS, then initial-* * izes system parameters as in cold boot. See the Cold Boot * * Loader listing for exactly what happens during warm and * * cold boots. * * * ************************************************************* wboot lxi sp,tpa ;Set up stack pointer mvi a,1 wflg equ $-1 ;Test if beginning or ana a ; ending a warm boot mvi a,1 sta wflg sta cwflg ;Set cold/warm boot flag jz gocpm xra a sta wflg mov c,a call djdrv ;Select drive A mvi c,0 ;Select single density call djden mvi c,0 ;Select side 0 call djside mvi a,15 ;Initialize the sector ; to read sta newsec lxi h,ccp-100h ;And the DMA address shld newdma call warmlod ;Read in CP/M lxi b,ccp+500h ;Load address for rest ;of warm boot call djdma mvi c,8 call djsec call warmrd jmp ccp+503h PAGE warmlod mvi a,15 ;Previous sector newsec equ $-1 inr a ;Update the previous sector inr a cpi 27 ;Was it the last ? jc nowrap sui 9 ;Yes cpi 19 rz lhld newdma lxi d,-480h dad d shld newdma nowrap sta newsec ;Save the new sector to read mov c,a call djsec lxi h,ccp-100h ;Get the previous DMA address newdma equ $-2 lxi d,100h ;Update the DMA address dad d shld newdma ;Save the DMA address mov b,h mov c,l call djdma ;Set the DMA address call warmrd jmp warmlod warmrd lxi b,retries*100h+0;Maximum # of errors wrmread push b call djtrk ;Set the track call djread ;Read the sector pop b rnc ;Continue if successful dcr b jnz wrmread ;Keep trying jmp djerr PAGE ************************************************************* * * * Setsec just saves the desired sector to seek to until an * * actual read or write is attempted. * * * ************************************************************* setsec mov a,c ;Save the sector number sta cpmsec ;CP/M sector # ret ************************************************************* * * * Setdma saves the DMA address for the data transfer. * * * ************************************************************* setdma mov h,b ;hl <- bc mov l,c shld cpmdma ;CP/M dma address ret ************************************************************* * * * Home is translated into a seek to track zero. * * * ************************************************************* home mvi c,0 ;Track to seek to ************************************************************* * * * 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 ************************************************************* * * * Sectran translates a logical sector # into a physical * * sector #. * * * ************************************************************* sectran inx b push d ;Save table address push b ;Save sector # call getdpb ;Get DPB address into HL mov a,m ;Get # of CP/M sectors/track ora a ;Clear cary rar ;Divide by two sub c push psw ;Save adjusted sector jm sidetwo sidea pop psw ;Discard adjusted sector pop b ;Restore sector requested pop d ;Restor address of xlt table sideone xchg ;hl <- &(translation table) dad b ;bc = offset into table mov l,m ;hl <- physical sector mvi h,0 ret sidetwo lxi b,15 ;Offset to side bit dad b mov a,m ani 8 ;Test for double sided jz sidea ;Media is only single sided pop psw ;Retrieve adjusted sector pop b cma ;Make sector request positive inr a mov 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 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. * * * ************************************************************* 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 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 0ch ;Strip off unwanted bits push psw ;Used to select a DPB rar lxi h,xlts ;Table of XLT addresses 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,8 ;Offset to DPB pointer dad d ;HL <- &DPH.DPB push h lhld origin+7 ;Get address of DJ terminal ; out routine inx h ;Bump to look at address of ; uart status location mov a,m xri 3 ;Adjust for proper rev DJ mov l,a mvi h,(origin+300h)/100h mov a,m ani dblsid ;Check double sided bit lxi d,dpb128s ;Base for single sided DPB's jnz sideok lxi d,dpb128d ;Base of double sided DPB's sideok xchg ;HL <- DBP base, DE <- &DPH.DPB pop d ;Restore DE (pointer into DPH) pop psw ;Offset to correct DPB ral ral mov c,a mvi b,0 dad b xchg ;Put DPB address in DPH mov m,e inx h mov m,d setdrv1 call getdpb ;Get address of DPB in HL lxi b,15 ;Offset to sector size dad b mov 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 currently * * selected drive, DE pointing to DPH. * * * ************************************************************* getdpb lda cpmdrv ;Get drive # mov l,a ;Form offset mvi h,0 dad h dad h dad h dad h lxi d,dpzero ;Base of DPH's dad d push h ;Save address of DPH lxi d,10 ;Offset to DPB dad d mov a,m ;Get low byte of DPB 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. * * * ************************************************************* 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 PAGE ************************************************************* * * * 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 into * * 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 over. ************************************************************* * * * 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 * * disk 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 * * contains the desired CP/M sector, then checks if it is * * the sector currently in the buffer. If no match is made, * * the buffer is flushed if necessary and the correct sector * * read from the disk. * * * ************************************************************* redwrt mvi b,0 ;The 0 is modified to contain secsiz equ $-1 ; the log2 of the physical ; sector size/128 on the ; currently selected disk. lda cpmsec ;Get the desired CP/M sector # push psw ;Temporary save ani 80h ;Save only the side bit mov c,a ;Remember the side pop psw ;Get the sector back ani 7fh ;Forget the side bit dcr a ;Temporary adjustment divloop dcr b ;Update repeat count jz divdone ora a ;Clear the carry flag rar ;Divide the CP/M sector # by ; the size of the physical ; sectors jmp divloop ; divdone inr a ora c ;Restore the side bit sta truesec ;Save the physical sector ; number lxi h,cpmdrv ;Pointer to desired drive, ; and sector lxi d,bufdrv ;Pointer to buffer drive, ; track and sector mvi b,4 ;Count loop dtslop dcr b ;Test if done with compare jz move ;Yes, match. Go move the data ldax d ;Get a byte to compare cmp m ;Test for match inx h ;Bump pointers to next data ; item inx d jz dtslop ;Match, continue testing PAGE ************************************************************* * * * Drive, track, and sector don't match, flush the buffer if * * necessary and then refill. * * * ************************************************************* call fill ;Fill the buffer with correct ; physical sector rc ;No good, return with error ; indication PAGE ************************************************************* * * * Move has been modified to cause either a transfer into or * * out the buffer. * * * ************************************************************* move lda cpmsec ;Get the CP/M sector to ; transfer dcr a ;Adjust to proper sector in ; buffer ani 0 ;Strip off high ordered bits secpsec equ $-1 ;The 0 is modified to ; represent the # of ; CP/M sectors per physical ; sector mov l,a ;Put into HL mvi h,0 dad h ;Form offset into buffer dad h dad h dad h dad h dad h dad h lxi d,buffer ;Beginning address of buffer dad d ;Form beginning address of ; sector to transfer xchg ;DE = address in buffer lxi h,0 ;Get DMA address, the 0 is ; modified to ; contain the DMA address cpmdma equ $-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 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 writtyp ;Set no directory write rnz ;No error exit ************************************************************* * * * Flush writes the contents of the buffer out to the disk * * if it has ever been written into. * * * ************************************************************* flush 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 ************************************************************* * * * 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 shld retryop ;Set up the read/write ; operation mvi b,retries ;Maximum number of retries ; to attempt retrylp push b ;Save the retry count lda bufdrv ;Get drive number involved ; in the operation mov c,a call djdrv ;Select the drive lda buftrk ana a ;Test for track zero mov c,a push b cz djhome ;Home the drive if track 0 pop b ;Restore track # call djtrk ;Seek to proper track lda bufsec ;Get sector involved ; in operation push psw ;Save the sector # rlc ;Bit 0 of A equals side # ani 1 ;Strip off unnecessary bits mov c,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 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 ************************************************************* * * * Fill fills the buffer with a new sector from the disk. * * * ************************************************************* fill call flush ;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 ************************************************************* * * * 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 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 routines. Iobyte is initialized by the * * cold boot routine, to modify, change the "intioby" equate.* * The I/O routines that follow all work exactly the * * same way. Using iobyte, they obtain the address to jump * * to in order to execute the desired function. There is a * * table with four entries for each of the possible * * assignments for each device. To modify the I/O routines * * for a different I/O configuration, just change the * * entries in the tables. * * * ************************************************************* ;I/O ROUTINES FOR NORTHSTAR MOTHERBOARD CONIN: CALL FLUSH ;FLUSH THE DISK BUFFER MVI E,1 ;CONSOLE INPUT CALL REDIR ; IOBYTE: 76543210 DW TTYIN ;CON: = TTY: XXXXXX00 DW CRTIN ;CON: = CRT: XXXXXX01 DW RDRIN ;CON: = BAT: XXXXXX10 DW UC1IN ;CON: = UC1: XXXXXX11 CONOUT: PUSH B ;SAVE THE CHARACTER CALL FLUSH ;FLUSH THE DISK BUFFER POP B ;RESTORE THE CHARACTER MVI E,1 ;CONSOLE OUTPUT CALL REDIR ; IOBYTE: 76543210 DW TTYOUT ;CON: = TTY: XXXXXX00 DW CRTOUT ;CON: = CRT: XXXXXX01 DW LSTOUT ;CON: = BAT: XXXXXX10 DW UC1OUT ;CON: = UC1: XXXXXX11 CONIST: MVI E,1 ;CONSOLE INPUT STATUS CALL REDIR ; IOBYTE: 76543210 DW TTYIST ;CON: = TTY: XXXXXX00 DW CRTIST ;CON: = CRT: XXXXXX01 DW RDRIST ;CON: = BAT: XXXXXX10 DW UC1IST ;CON: = UC1: XXXXXX11 RDRIN: MVI E,7 ;READER INPUT CALL REDIR ; IOBYTE: 76543210 DW TTYIN ;RDR: = TTY: XXXX00XX DW PTRIN ;RDR: = PTR: XXXX01XX DW UR1IN ;RDR: = UR1: XXXX10XX DW UR2IN ;RDR: = UR2: XXXX11XX RDRIST: MVI E,7 ;READER INPUT STATUS CALL REDIR ; IOBYTE: 76543210 DW TTYIST ;RDR: = TTY: XXXX00XX DW PTRIST ;RDR: = PTR: XXXX01XX DW UR1IST ;RDR: = UR1: XXXX10XX DW UR2IST ;RDR: = UR2: XXXX11XX PUNOUT: MVI E,5 ;PUNCH OUTPUT CALL REDIR ; IOBYTE: 76543210 DW TTYOUT ;PUN: = TTY: XX00XXXX DW PTPOUT ;PUN: = PTP: XX01XXXX DW UP1OUT ;PUN: = UP1: XX10XXXX DW UP2OUT ;PUN: = UP2: XX11XXXX LSTOUT: MVI E,3 ;LIST OUTPUT CALL REDIR ; IOBYTE: 76543210 DW TTYOUT ;LST: = TTY: 00XXXXXX DW CRTOUT ;LST: = CRT: 01XXXXXX DW LPTOUT ;LST: = LPT: 10XXXXXX DW UL1OUT ;LST: = UL1: 11XXXXXX LSTOST: MVI E,3 ;LIST OUTPUT STATUS CALL REDIR ; IOBYTE: 76543210 DW TTYOST ;LST: = TTY: 00XXXXXX DW CRTOST ;LST: = CRT: 01XXXXXX DW LPTOST ;LST: = LPT: 10XXXXXX DW UL1OST ;LST: = UL1: 11XXXXXX REDIR: LDA IOBYTE ;GET THE INTEL STANDARD ; IOBYTE REDIR0: RLC ;SHIFT THE NEXT FIELD IN DCR E ;BUMP THE SHIFT COUNT JNZ REDIR0 REDIR1: ANI 110B ;MASK THE REDIRECTION ; FIELD MOV E,A ;MAKE THE WORD TABLE ; OFFSET MVI D,0 POP H ;GET THE TABLE BASE DAD D ;OFFSET INTO OUR TABLE MOV A,M ;LOAD THE LOW LEVEL I/O ; ROUTINE POINTER INX H MOV H,M MOV L,A PCHL ;EXECUTE THE LOW LEVEL ; I/O DRIVER PAGE ************************************************************* * * * CONYTP: 6 NORTH STAR * * * * THE FOLLOWING CODE IMPLEMENTS THE NORTH STAR CONSOLE I/O * * SYSTEM. THIS SYSTEM IS FOR USERS WHO PURCHASE A MORROW * * DESIGNS DISK SYSTEM TO REPLACE THEIR NORTH STAR DISK * * SYSTEM. THE MAPPING OF THE LOGICAL TO PHYSICAL ENTRY * * POINTS IS PERFORMED AS FOLLOWS: * * * * DEVICE NAME LEFT RIGHT PARALLEL * * SERIAL SERIAL PORT * * * * CONSOLE CON: = TTY: CRT: UC1: * * READER RDR: = TTY: PTR: UR1: * * PUNCH PUN: = TTY: PTP: UP1: * * LIST LST: = TTY: CRT: UL1: * * * * FOR EXAMPLE, TO USE A PRINTER CONNECTED TO THE RIGHT * * SERIAL PORT, USE THE CP/M COMMAND: * * * * STAT LST:=CRT: * * * * LIKEWISE, THE CP/M COMMAND "STAT LST:=UL1:" IS USED IF * * YOU HAVE A PRINTER CONNECTED TO THE PARALLEL PORT. * * * ************************************************************* NSLDAT EQU 2 ;LEFT SERIAL PORT DATA PORT NSLSTA EQU 3 ;LEFT SERIAL PORT STATUS PORT NSRDAT EQU 4 ;RIGHT SERIAL PORT DATA PORT NSRSTA EQU 5 ;RIGHT SERIAL PORT STATUS PORT NSSTBE EQU 1 ;TRANSMITTER BUFFER EMPTY ; STATUS BIT NSSRBR EQU 2 ;RECIEVER BUFFER READY ; STATUS BIT ;SEE THE 8251 DATA SHEETS FOR ; MORE CONFIGURATION ; INFORMATION. PAGE NSLIN1 EQU 0CEH ;LEFT SERIAL PORT ; INITIALIZATION # 1 NSRIN1 EQU 0CEH ;RIGHT SERIAL PORT ; INITIALIZATION # 1 ;76543210 BIT DEFINATIONS ;11001110 DEFAULT ; CONFIGURATION ;XXXXXX00 SYNCHRONOUS MODE ;XXXXXX01 1X CLOCK RATE ;XXXXXX10 16X CLOCK RATE ;XXXXXX11 64X CLOCK RATE ;XXXX00XX 5 BIT CHARACTERS ;XXXX01XX 6 BIT CHARACTERS ;XXXX10XX 7 BIT CHARACTERS ;XXXX11XX 8 BIT CHARACTERS ;XXX0XXXX PARITY DISBABLE ;XXX1XXXX PARITY ENABLE ;XX0XXXXX ODD PARITY ; GENERATION/CHECK ;XX1XXXXX EVEN PARITY ; GENERATION/CHECK ;00XXXXXX INVALID ;01XXXXXX 1 STOP BIT ;10XXXXXX 1.5 STOP BITS ;11XXXXXX 2 STOP BITS NSLIN2 EQU 37H ;LEFT SERIAL PORT ; INITIALIZATION # 2 NSRIN2 EQU 37H ;RIGHT SERIAL PORT ; INITIALIZATION # 2 ;76543210 BIT DEFINATIONS ;00110111 DEFAULT ; CONFIGURATION ;XXXXXXX1 ENABLE TRANSMITTER ;XXXXXX1X ASSERT DTR* ;XXXXX1XX ENABLE RECIEVER ;XXXX1XXX SEND BREAK ; CHARACTER, TXD LOW ;XXX1XXXX RESET PE, OE, FE ; ERROR FLAGS ;XX1XXXXX ASSERT RTS* ;X1XXXXXX INTERNAL RESET ;1XXXXXXX ENTER HUNT MODE ; FOR (SYNC) NSPDAT EQU 0 ;PARALLEL DATA PORT NSPSTA EQU 6 ;PARALLEL STATUS PORT NSPRBR EQU 1 ;RECIEVER BUFFER READY ; STATUS BIT NSPTBE EQU 2 ;TRANSMITTER BUFFER EMPTY ; STATUS BIT NSRAM EQU 0C0H ;NORTH STAR MEMORY PARITY ; PORT, SET TO 0 FOR NO ; NORTHSTAR RAM PAGE ************************************************************* * * * LEFT SERIAL PORT ROUTINES. USE TTY: DEVICE. * * * ************************************************************* TTYIN: ;READ A CHARACTER IN NSLSTA ANI NSSRBR JZ TTYIN ;WAIT TILL A CHARACTER IS ; READY IN NSLDAT ;GET THE CHARACTER ANI 7FH ;STRIP PARITY RET TTYOUT: ;WRITE A CHARACTER IN NSLSTA ANI NSSTBE JZ TTYOUT ;WAIT TILL THE BUFFER IS ; EMPTY MOV A,C ;WRITE THE CHARACTER OUT NSLDAT RET TTYIST: ;RETURN INPUT BUFFER STATUS IN NSLSTA ANI NSSRBR RZ ;RETURN NOT READY MVI A,0FFH RET ;THERE IS A CHARACTER READY TTYOST: ;RETURN OUTPUT BUFFER STATUS IN NSLSTA ANI NSSTBE RZ ;RETURN NOT READY MVI A,0FFH RET ;RETURN READY PAGE ************************************************************* * * * RIGHT SERIAL PORT ROUTINES. USE CRT:, PTR:, * * AND PTP: DEVICES. * * * ************************************************************* CRTIN: ;READ A CHARACTER PTRIN: IN NSRSTA ANI NSSRBR JZ CRTIN ;WAIT TILL A CHARACTER IS ; READY IN NSRDAT ;GET THE CHARACTER ANI 7FH ;STRIP PARITY RET CRTOUT: ;WRITE A CHARACTER PTPOUT: IN NSRSTA ANI NSSTBE JZ CRTOUT ;WAIT TILL THE BUFFER IS ; EMPTY MOV A,C ;WRITE THE CHARACTER OUT NSRDAT RET CRTIST: ;RETURN INPUT BUFFER STATUS PTRIST: IN NSRSTA ANI NSSRBR RZ ;RETURN NOT READY MVI A,0FFH RET ;THERE IS A CHARACTER READY CRTOST: ;RETURN OUTPUT BUFFER STATUS IN NSRSTA ANI NSSTBE RZ ;RETURN NOT READY MVI A,0FFH RET ;RETURN READY PAGE ************************************************************* * * * PARALLEL PORT ROUTINES. USE UC1:, UR1:, UR2:, UP1:, * * UP2:, LPT:, AND UL1: DEVICES. * * * ************************************************************* UC1IN: ;READ A CHARACTER UR1IN: UR2IN: IN NSPSTA ANI NSPRBR JZ UC1IN ;WAIT TILL A CHARACTER IS ; READY IN NSPDAT ;GET THE CHARACTER PUSH PSW MVI A,30H ;RESET THE PARALLEL INPUT ; FLAG OUT NSPSTA POP PSW ANI 7FH ;STRIP PARITY RET UC1OUT: ;WRITE A CHARACTER UP1OUT: UP2OUT: LPTOUT: UL1OUT: IN NSPSTA ANI NSPTBE JZ UC1OUT ;WAIT TILL THE BUFFER IS ; EMPTY MVI A,20H ;RESET THE PARALLEL OUTPUT ; FLAG OUT NSPSTA MOV A,C ;WRITE THE CHARACTER, STROBE ; BIT 7 NSPOUT: ORI 80H OUT NSPDAT ANI 7FH OUT NSPDAT ORI 80H OUT NSPDAT RET UC1IST: ;RETURN INPUT BUFFER STATUS UR1IST: UR2IST: IN NSPSTA ANI NSPRBR RZ ;RETURN NOT READY MVI A,0FFH RET ;RETURN READY PAGE LPTOST: ;RETURN OUTPUT BUFFER STATUS UL1OST: IN NSPSTA ANI NSPTBE RZ ;RETURN NOT READY MVI A,0FFH RET ;RETURN READY ************************************************************* * * * Tinit can be modified for different I/O setups. * * * ************************************************************* tinit mvi c,clear ;Initialize the terminal ; routine mvi a,intioby ;Initialize IOBYTE sta iobyte jmp cout 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 are 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 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,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 ************************************************************* * * * 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.0. * * * ************************************************************* ************************************************************* * * * The following DPB defines a diskette for 128 byte * * sectors, single density, and single sided. * * * ************************************************************* dpb128s dw 26 ;CP/M sectors/track db 3 ;BSH db 7 ;BLM db 0 ;EXM dw 242 ;DSM dw 63 ;DRM db 0c0h ;AL0 db 0 ;AL1 dw 16 ;CKS dw 2 ;OFF db 1h ;16*((#cpm sectors/physical ;sector) -1) + log2(#bytes ;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 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 12h ;16*((#cpm sectors/physical ;sector) -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. * * * ************************************************************* 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 33h ;16*((#cpm sectors/physical ;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. * * * ************************************************************* 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 74h ;16*((#cpm 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. * * * ************************************************************* 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 9h ************************************************************* * * * The following DPB defines 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 db 0 ;AL1 dw 64 ;CKS dw 2 ;OFF db 1ah PAGE ************************************************************* * * * The following DPB defines a diskette as 512 byte sectors, * * double density, and double sided. * * * ************************************************************* 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 3bh ************************************************************* * * * 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 db 0 ;EXM dw 599 ;DSM dw 255 ;DRM db 0f0h ;AL0 db 0 ;AL1 dw 64 ;CKS dw 2 ;OFF db 7ch PAGE ************************************************************* * * * CP/M disk parameter headers, unitialized. * * * ************************************************************* dpzero dw 0 ;Address of translation table ; (filled in by setdrv) dw 0,0,0 ;Used by BDOS dw dirbuf ;Address of directory buffer dw 0 ;Address of DPB (filled in ; by setdrv) dw csv0 ;Directory check vector dw alv0 ;Allocation vector dpone dw 0 dw 0,0,0 dw dirbuf dw 0 dw csv1 dw alv1 dptwo dw 0 dw 0,0,0 dw dirbuf dw 0 dw csv2 dw alv2 dpthre dw 0 dw 0,0,0 dw dirbuf dw 0 dw csv3 dw alv3 PAGE ************************************************************* * * * 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 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 alv0 ds 75 ;Allocation vector for drv A alv1 ds 75 ;Allocation vector for drv B alv2 ds 75 ;Allocation vector for drv C alv3 ds 75 ;Allocation vector for drv D csv0 ds 64 ;Directory check vector ; drive A csv1 ds 64 ;Directory check vector ; drive B csv2 ds 64 ;Directory check vector ; drive C csv3 ds 64 ;Directory check vector ; drive D dirbuf ds 128 ;Directory buffer end