rn from console status (flag in al). ; console input. conin: if not loader call const ; get status. or al,al ; see if ready. jz conin ; wait for ready if not. push dx ; save dx. mov dx,condat ; get console data port adr. in al,dx ; read console data. pop dx ; restore dx. and al,7fh ; strip parity. endif ret ; return from console input (char in al). ; console output. conout: push dx ; save dx. mov dx,consts ; get status port adr. conolp: in al,dx ; store dx. endif ret ; ********************************************************* ; ************** get & set i/o byte contents ************** ; ********************************************************* ; return io byte (not implemented, but storage allocated). retiobt: mov al,iobyte ; al gets iobyte contents. ret ; set io byte (not implemented, but storage allocated). setiobt: mov iobyte,cl ; iobyte get contents of cl. st_ext: ret ; ****************************y, out dx,al mov al,07h ; 8 data bits, 1 stop bit. out dx,al mov dx,lptsts ; get clock select port. mov al,(lbaud shl 4)+lbaud ; get baud rate code. out dx,al ; set baud rate. mov dx,lptcom ; get command port. mov al,45h ; reset errors, enable. out dx,al endif ; Print sign-on message (different for loader or bios). mov bx,(offset signon) call prtmsg ; print signon. ; the system locates the top of ram memory, and ; sets up the memory segment table to reflect nt to offset. mov al,0 ; clear. adc al,cl ; add top 4 & carry. mov msb20,al ; save bits a16-a19. mov lsb20,dx ; save bits a00-a15. ret ; ********************************************************* ; ******************* warm-start entry ******************** ; ********************************************************* warmstart: ; no special housekeeping required in this configuration. ; just re-entry the ccp. jmp ccp+6 ; ********************************************read status port. and al,contbe ; test for ready. jz conolp ; result zero, cont test (00=not ready). mov al,cl ; get character from cl. mov dx,condat ; get console data port adr. out dx,al ; send character to console. pop dx ; restore dx. ret ; return from console output. ; printer status check. pollpt: if not loader push dx ; save dx. mov dx,lptsts ; get printer status port adr. in al,dx ; read printer status. and al,lpttbe ; mask for desired bits. jz ps_ext ; ex disk interface routines *************** ; ********************************************************* ; select disk & disk density of unit given by cl. seldsk: mov drvltr,cl ; save letter code (0-15). xor bx,bx ; clear bx for possible error. mov ch,0 ; clear upper cx for index. mov si,offset drvmap ; get drive map table address. add si,cx ; figure address of entry. mov al,[si] ; get physical drive number. cmp al,0ffh ; is it undefined? jz st_ext ; error to cpm if sSee if it's an IBM format first. test cl,4 ; is it an 8-inch drive? jnz nonibm ; hop if so. mov dx,offset chkbuf ; get destination offset. mov ax,cs ; get destination segment. call comdma ; compute dma address. call rdadr ; read address bytes. jnz nonibm ; hop if not. ; must be ibm format, so no need to do all that stuff below. mov al,clatch ; set side 1 bit in latch. or al,40h mov dx,fcont ; get latch port adr. out dx,al ; send to latch. mov clatch,al call rdad 1 for double density, ; bit 1 = 1 for double sided, ; bit 2 = 1 for 512-byte sectors. loged: mov bx,(offset dpbt5) ; 5" dpb table address. mov cl,sekdsk ; get drive number. test cl,4 ; is it 5-inch floppy? jz loged5 ; hop if so. mov bx,(offset dpbt8) ; 8" floppy dpb table address. loged5: test byte ptr [bx],0ffh ; is it last table entry (0)? jz setden ; hop out of loop if so. cmp al,[bx] ; is it this density code? jz setden ; hop out of loop if so. add bx,3 ; else. pop cx ; restore drive to map. mov byte ptr hstwrt,0 ; not dirty anymore. hrdse1: sub cl,8 ; hard disk drives 0 up. call mapper ; log in hard disk drive. jnc index ; return with address of dph. xor bx,bx ; else return with error. endif ret ; Read the next id field into chkbuf. rdadr: mov cx,0c4d0h ; read address code. mov dx,04006h ; disk-memory, 6 bytes. call dmarwe ; read 6 bytes into chkbuf. and al,9dh ; did it read ok? ret ; home currently selected do. mov cl,al ; get physical drive number. mov sekdsk,cl ; save new disk number. cmp cl,8 ; is it a hard disk drive? jc selflp ; hop if not. jmp hrdsel ; jump if so. selflp: mov bx,(offset drvflg) ; point to density table. add bx,cx ; offset into table. and dl,fresh ; fresh access? jnz norst ; no, leave control table alone. mov hstact,0 ; clear host active flag mov word ptr unacnt,0 ; clear unallocated count. mov [bx],ch ; clear tabled control flag. mov dens,ch ;r ; read next address info. mov al,0ffh ; get double-sided ibm code. jz selsid ; set sidedness. mov al,0feh ; get single-sided ibm code. selsid: pop bx ; get density flag adr back. jmps selnz ; hop to figure rest of it. ; must not be ibm format, so read single density sector 1. nonibm: mov al,clatch ; get current latch value. or al,10h ; set to single density. mov dx,fcont ; get latch port address. out dx,al ; set floppy control latch. mov clatch,al ; save the value. to next code entry. jmps loged5 ; try the next one. setden: inc bx ; point at address. mov dx,word ptr [bx] ; get Disk Parameter Block adr. mov bx,dx ; put it in bx. mov al,[bx] ; get density byte from table. mov dens,al ; set current drive density. inc bx ; bump past density byte. xchg bx,dx ; put table pointer in dx. push dx ; save table pointer. call index ; compute addr of overlay area. pop dx ; get table pointer. xchg bx,dx ; source address in bx. movrive. home: cmp sekdsk,8 ; is it a hard disk drive? jc homed ; hop if not. or byte ptr hstwrt,0 ; write pending? jnz homed mov hstact,0 ;clear host active flag mov hsttrk,0 ; set track = 0. homed: mov cx,0 ;now, set track zero ; set track address given by cx. settrk: mov sektrk,CX ;track to seek ret ; set track sector address given by cx. setsec: mov seksec,cx ;sector to seek ret ; translate sector cx using table at [dx], result in bx. sectrn: xchg bx,cx clear current flag. mov byte ptr diskno,0ffh ; force new controller setup. norst: mov al,[bx] ; get flag. test al,al ; check for zero. jz notlog ; skip if not logged in. jmp loged ; jump if already logged in. notlog: push bx ; save flag address. ; read stuff from track 0 to determine format of disk. mov al,cl ; get drive number. test al,4 ; is it 5 or 8-inch? jz norst5 ; hop if 5-inch. or al,8 ; set ENMF* bit. norst5: mov dx,fcont ; get floppy control port a mov bx,dmaoff ; get current disk offset. push bx ; save address value. mov dmaoff,(offset chkbuf) ; use temporary buffer. mov bx,dmaseg ; get current disk segment. push bx ; save address value. mov dmaseg,cs ; get out local segment. call read ; bios read routine. pop bx ; recover original disk segment. mov dmaseg,bx ; restore to pointer. pop bx ; recover original offset. mov dmaoff,bx ; restore to pointer. pop bx ; restore density flag address. mov al,chkbuf+7eh ax,[bx] ; get xlt table pointer. xchg bx,dx ; destination address in bx. mov [bx],ax ; put xlt pointer into dph table. add bx,10 ; add offset to dpb area. add dx,2 ; bump past xlt pointer. mov [bx],dx ; put descriptor addr into dph table. mov curspc,cpmspt ; set current sectors per cylinder. index: xor bh,bh ; load disk number and zero byte. mov bl,sekdsk mov dx,(offset dphtab) ; get disk param header table adr. shl bx,1 ; drive number times 2. add bx,dx ; figure ; use bx for intermediate. cmp sekdsk,8 ; is it a hard disk drive? jnc sc_ext ; hop if so. test dens,04h ; test for deblocked disk. jnz sc_ext ; if deblocked - no xlate. inc bl ; just bump the sector. or dx,dx ; are we using a xlat table? jz sc_ext ; no, exit with inc sector number. dec bl ; make address again. add bx,dx ; add sector # to xlate base. mov bl,[bx] ; get xlated sector from xlate table. mov bh,0 ; top is zeroed. sc_ext: mov ax,bx ; for mpm compatid. out dx,al ; tell controller which disk. mov clatch,al ; save the value. mov word ptr seksec,1 ; set sector 1. mov al,stprat+hlab ; restore at fast steprate. mov dx,fdisk ; get command port adr. out dx,al ; start restore. call waitio ; wait for completion. mov bx,(offset trtab) ; get address of track table. if dual ; if persci drive and cl,2 ; index to 1 of 2 entries endif add bx,cx ; add drive offset mov byte ptr [bx],00h ; set to track 0 mov sektrk,0 ; ; get special byte from buffer. or al,al ; is it a zero? jnz selnz ; hop if not. mov al,0e5h ; big trouble for it to be zero. selnz: mov [bx],al ; put in density table. ; This is where we figure out what density and how many sides. ; Note that there are two kinds of density codes. The one ; stored in the density table at drvflg is the one that comes ; from the first sector of the floppy disk itself. The one ; that's stored at dens is different, and is coded thusly: ; bit 0 = table entry address. mov dx,word ptr [bx] ; get address of dph from table. mov bx,dx ; put it in bx. ret ; return from seldsk (& other places). ; Hard disk select routine. hrdsel: if nhard gt 0 ; if one or more hard disk drives. mov curspc,cpmspc ; set current sectors/cylinder. and dl,fresh ; first access? jnz index ; return with dph adr if so. or byte ptr hstwrt,0 ; is dirty flag set? jz hrdse1 ; hop if not. push cx ; save drive to map. call writehst ; update disk ; test for track 0 jz read1 ; if track 0 don't deblock test dens,04h ; test for deblocked jz read1 ; if not deblocked readh: mov word ptr unacnt,0 ; clear unallocated counter. mov readop,1 ; read operation mov rsflag,1 ; must read data mov wrtype,wrual ; treat as unalloc jmp rwoper ; use deblock routines ; to perform the read. read1: mov dl,sekdsk ; put drive # in dl call seekls ; seek the disk to the proper track. mov dx,dmaoff ; get destination offset. mov at status bits. mov ch,8 ; eight bits in status. bitlop: mov cl,'0' ; assume bit is 0. rol ah,1 ; test next bit. jnc prtbit ; it's off, leave 0. inc cl ; it's on, make 1. prtbit: call conout ; print bit value. dec ch ; dec bit counter. jnz bitlop ; print all bits. or al,255 ; set error code for bdos. rc_ext: ret ; convert cl to decimal and display at console. prtdec: xor ch,ch ; clear top eight bits. decout: push dx ; save value on stack. mov dtries endif mov bx,(offset trtab) ; point at track table add bx,dx ; add index mov al,[bx] ; get old track # push dx ; save dx. mov dx,ftrk ; get track port adr. out dx,al ; update track register. pop dx ; restore dx. mov bl,cl ; save track # in bl mov dl,byte ptr diskno ; get drive # or dl,10h ; set single density bit. mov bh,dl ; save in bh mov al,byte ptr dens ; get density type byte test al,00001000b ; is it ibm compatible? jz seekni ; hop if not ib; restore cx. ret ; return from seek. nothr: ; note: this routine is to allow time for the drive ; tunnel erase to terminate before moving the ; head. the delay is aprx. 700 micro-seconds. mov al,0 ; delay count = 256. busy1: dec al ; decrease count. jnz busy1 ; loop till zero. mov al,cl ; put dest. in al from cl. push dx ; save dx. mov dx,fdata ; get data port adr. out dx,al ; track to data register. mov al,14h+stprat+hlab ; seek command. mov dx,fdisk ; gx,dmaseg ; get destination segment. call comdma ; compute physical dma adr. mov ercnt,rtcnt ; reset read retry error counter. rretry: mov ax,seksec ; get sector to read mov cx,088d0h ; floppy read, force interupt cmds. mov dx,04080h ; dma read, dma count 128 bytes. call dmarw ; enter common r/w routine. mov ercode,al ; save status bits. and al,09dh ; look at error bits. jz rc_ext ; none set, return from read. dec ercnt ; decrement retry counter. jnz rretry ; if not zx,-1 ; this becomes number / radix. sub10: sub cx,10 ; subtract 10. inc dx ; inc remainder. jnc sub10 ; loop till carry out. add cx,10 ; add radix back in. xchg dx,cx ; switch new/current. test cx,cx ; test for zero reminder. jz cndone ; if zero, conversion complete. call decout ; build bcd digits recursivly. cndone: mov cl,dl ; get bcd value. add cl,'0' ; add ascii bias. call conout ; print the digit. pop dx ; recover next bcd value. ret ; print m. ; ibm compatible 5-inch, so check for track greater than 39. and bh,0efh ; clear single density bit. cmp bl,ibmtpd ; is track greater than 39? jc trksd5 ; hop if not. mov al,2*ibmtpd-1 ; subtrack track no. from 80. sub al,bl mov bl,al or bh,40h ; set side select bit. jmps trksd5 ; finish below. seekni: or bl,bl ; is it track zero? jz trksd ; hop if so. test al,2 ; test for double sided jz trkss ; don't /2 if single sided ; figure track to go to and whiet command port adr. out dx,al ; set rate, seek with verify. pop dx ; restore dx. call waitio ; poll process complete. push dx ; save dx. mov dx,fdisk ; get status port adr. in al,dx ; read status. pop dx ; restore dx. mov ercode,al ; save status bits. test al,91h ; look at success bits. jnz skerr ; zero if ok. pop cx ; restore track # mov dx,diskno ; get drive index if dual ; if using persci drives. and dl,2 ; index to 1 of 2 entries endif mov bxero retry read. mov al,1 ; read error flag. ; disk error handler: on entry al = error type. ; print type, track, sector, & status. ; set error code and return to bdos. recov: push ax ; save error flag. mov bx,(offset errmsg) call prtmsg ; error intro message. pop ax ; get flag back. xor ah,ah ; clear high bits. mov cl,7 ; table offset. mul cl ; multiply by offset. inc bx ; past eom. add bx,ax ; add offset. call prtmsg ; print the error type. mov ball digits recursivly. ; ; seek floppy disk in dl to track in cl ; update track table for the drive and return with al = 0 ; if no error. otherwise print error status and return ; perform read id function to recalibrate disk if seek error. ; seekls: mov trk,cl ; save track # cmp byte ptr diskno,dl ; test for new drive jz samedsk ; not a new drive so just seek. mov byte ptr diskno,dl ; update current disk # ; new drive so get present track and seek to it to ; to inform the controllch side to select. test bl,1 ; is it an even track no? jz trkev ; hop if so. or bh,40h ; or in side select if so. trkev: shr bl,1 ; divide track by 2. trkss: test al,1 ; test for double density jz trksd ; hop if single density. and bh,0efh ; clear single density bit. trksd: test dl,4 ; is it 5 or 8-inch floppy? jz trksd5 ; hop if 5-inch floppy. or bh,8 ; set weird bit 3 if 8-inch. trksd5: mov al,bh ; get density-select code push dx ; save dx. mov dx,fcont ; g,(offset trtab) ; point at track table add bx,dx ; add index mov [bx],cl ; update track table ret ; return seek ok. skerr: dec sercnt ; decrement error counter. jnz sretry ; retry if not zero. pop cx ; recover cx. xor al,al ; seek error flag. jmp recov ; return from seek with error set. ; check for seek to correct track, re-seek if necessary. sretry: mov cx,0c4d0h ; read addr, force interrupt. mov dx,04006h ; dma read, count byte. call dmarwe ; read id using x,(offset drvmsg) call prtmsg ; drive message. mov cl,drvltr ; get drive letter code. add cl,'A' ; make into actual letter. call conout ; print the letter. inc bx ; past eom. call prtmsg ; track message. mov cl,trk ; get current track #. call prtdec ; print in decimal. inc bx ; past eom. call prtmsg ; sector message. mov cl,sect ; get current sector #. call prtdec ; print in decimal. inc bx ; past eom. call prtmsg ; status message. mov ah,ercode ; geer that the head is unloaded. push dx ; save dx. mov dx,ftrk ; get track register port. in al,dx ; read track register. mov dx,fdata ; get data port. out dx,al ; send track to data port. mov al,10h ; get seek command no verify mov dx,fdisk ; get command port adr. out dx,al ; do the (non) seek. call waitio ; wait till done pop dx ; restore dx. ; setup density & such samedsk: xor dh,dh ; clear dh if dual ; if persci drive and dl,2 ; index to 1 of 2 enet floppy control port. out dx,al ; set up the latch. mov clatch,al ; save the value. pop dx ; restore dx. mov cl,bl ; put track in cl. ; perform actual seek to track given by cl. seek: push cx ; save cx. mov sercnt,srtcnt ; reset seek retry error counter. push dx ; save dx. mov dx,ftrk ; get track register port. in al,dx ; read present track no. pop dx ; restore dx. cmp al,cl ; same as new track number? jnz nothr ; nope, go move it. there: pop cx er of proper track. pop dx ; restore dx. chks2: pop cx ; restore track #. jmp seek ; move head to it. ; ; common dma read & write subroutine. ; dmarw: ; set floppy sector register from sect. mov sect,al ; save sector #. push dx ; save dx. mov dx,fsect ; get sector port adr. out dx,al ; set sector number. pop dx ; restore dx. dmarwe: push cx ; save cx. push dx ; save dx. mov dx,fdisk ; get floppy status port. in al,dx ; read floppy status. test restore floppy read/write comd. mov al,ch ; get floppy read/write command. mov dx,fdisk ; get floppy command port adr. out dx,al ; start read or write operation. call waitio ; wait for read or write done. ret dma_xt: pop dx ; restore dx. pop cx ; restore cx. ret ; return from dma common. ; write the selected cp/m sector. write: if not loader mov wrtype,cl ; save write type cmp sekdsk,8 ; is it a hard disk drive? jnc writeb ; hop if so. mov cx,sektrk ; get t poldma: push dx ; save dx. mov dx,dmatc0 ; get transfer count port. poldml: in ax,dx ; read count register. test ax,ax ; is it zero yet? jnz poldml ; loop back if not. pop dx ; restore dx. ret ; return from poldma. ; ; deblocked read and write routines. ; ; writeb: if not loader ;write the selected CP/M sector mov readop,0 ;write operation mov cl,wrtype cmp cl,wrual ;write unallocated? jnz chkuna ;check for unalloc ; ; write to unallocated, set paramed record, requires pre-read mov word ptr unacnt,0 ; unacnt = 0. mov rsflag,1 ;rsflag = 1 ;drop through to rwoper ; ;***************************************************** ;* * ;* Common code for READ and WRITE follows * ;* * ;***************************************************** rwoper: ;enter here to perform the read/write mov erflag,0 ;no errors (yet) mov ax,seksec ;compute hoal,80h ; is floppy ready? jnz dma_xt ; hop out if not ready. ; get floppy port address and memory transfer address. mov al,msb20 ; get 4 hi bits of adress. mov ah,0 ; get 4 hi bits of floppy port. mov bx,lsb20 ; get 16 lo bits of address. mov cx,fdata ; get 16 lo bits of floppy port. pop dx ; get command flag and count. push dx ; save it back. test dh,80h ; is it a write or read op? mov dx,fdmard ; get dma read command. jz dmard ; must be read if bit 7=0. xchg arack # or cx,cx ; test for track 0 jz write1 ; if track 0 don't deblock test dens,04h ; test for deblocked jnz writeb write1: mov dl,sekdsk ; put drive # in dl call seekls ; seek the disk to the proper track. call precmp ; set or clear write precomp. mov dx,dmaoff ; get source offset. mov ax,dmaseg ; get source segment. call comdma ; compute physcial address. mov ercnt,rtcnt ; reset write retry error counter. wretry: mov ax,seksec ; get sector to write. mov cx,0a0ters ; cmp sekdsk,8 ; is it a hard disk? jnc blkset ; hop if so. test dens,02h ;test for double sided jnz blkset mov word ptr unacnt,16 ; 2048-byte blocks. jmp blkset1 blkset: mov word ptr unacnt,32 ; 4096-byte blocks. blkset1: mov al,sekdsk ;disk to seek mov unadsk,al ;unadsk = sekdsk mov ax,sektrk mov unatrk,ax ;unatrk = sektrk mov ax,seksec mov unasec,ax ;unasec = seksec ; chkuna: ;check for write to unallocated sector ; mov bx,offset unacnt ;point "UNA" at Ust sector mov cl,secshf shr ax,cl mov sekhst,ax ;host sector to seek ; ; active host sector? mov al,1 xchg al,hstact ;always becomes 1 test al,al ;was it already? jz filhst ;fill host if not ; ; host buffer active, same as seek buffer? mov al,sekdsk cmp al,hstdsk ;sekdsk = hstdsk? jnz nomatch ; ; same disk, same track? mov ax,hsttrk cmp ax,sektrk ;host track same as seek track jnz nomatch ; ; same disk, same track, same buffer? mov ax,sekhst cmp ax,hstsec ;sl,ah ; exchange source and dest ptrs. xchg bx,cx mov dx,fdmawt ; get dma write command. dmard: push dx ; save on stack. ; at this point: destination=bx,al; source=cx,ah. mov dx,dmadpu0 ; get dest upper port. out dx,ax ; set destination upper. mov al,ah ; get source upper in al. mov dx,dmaspu0 ; get source upper port. out dx,ax ; set source upper. mov ax,bx ; get destinaiton lower. mov dx,dmadpl0 ; get dest lower port. out dx,ax ; set destination lower. mov ax,cd0h ; floppy write, force interrupt cmds. mov dx,08080h ; dma write, dma count byte cmds. call dmarw ; enter common r/w routine. mov ercode,al ; save status bits. and al,0fdh ; look at error bits. jz w_exit ; none set, return from write. dec ercnt ; decrement retry counter. jnz wretry ; if not zero retry write. mov al,2 ; write error flag. jmp recov ; go set error, return from write. endif ; poll for last activity completed. waitio: call fdelay ; wait for valiNACNT mov ax,[bx] ; get unallocated count. test ax,ax ;any unalloc remain? jz alloc ;skip if not ; ; more unallocated records remain dec ax ;unacnt = unacnt-1 mov [bx],ax ; set new unacnt. mov al,sekdsk ;same disk? mov BX,offset unadsk cmp al,byte ptr [bx] jnz alloc ;skip if not ; ; disks are the same mov AX,unatrk cmp AX,sektrk jnz alloc ;skip if not ; ; tracks are the same mov ax,seksec ;same sector? ; mov BX,offset unasec ;point una at unasec ; cmp axekhst = hstsec? jz match ;skip if match nomatch: ;proper disk, but not correct sector mov al,hstwrt test al,al ;"dirty" buffer ? jz filhst ;no, don't need to write call writehst ;yes, clear host buff mov al,erflag ;get error flag or al,al ;test error flag jnz return_rw ;exit on error ; filhst: ;may have to fill the host buffer mov al,sekdsk mov hstdsk,al mov ax,sektrk mov hsttrk,ax mov ax,sekhst mov hstsec,ax mov al,rsflag test al,al ;need to read? jz fix ; get source lower. mov dx,dmaspl0 ; get source lower port. out dx,ax ; set source lower. ; set dma count and command. pop bx ; restore read or write comd. pop ax ; restore transfer count. and ah,3fh ; clear old command bits. mov dx,dmatc0 ; get transfer count port. out dx,ax ; set transfer count. mov ax,bx ; get read or write command. mov dx,dmacon0 ; get dma control port. out dx,ax ; initialize dma operation. ; start floppy controller running. pop cx ; d status. push dx ; save dx. mov dx,fdisk ; get floppy status port. waitil: in al,dx ; read status. test al,1 ; is it busy doing something? jnz waitil ; loop back if so. pop dx ; restore dx. w_exit: ret ; return from waitio. ; Provide a delay after commands for status to become valid. fdelay: push cx ; save cx. mov cx,80h ; this seems to work. fdloop: loop fdloop ; count down till cx=0. pop cx ; restore cx. ret ; poll for current dma activity completed. ,[bx] ; seksec = unasec? jnz alloc ;skip if not ; ; match, move to next sector for future ref inc word ptr [bx] ; unasec = unasec+1. mov ax,[bx] ; end of track? cmp ax,curspc ; count CP/M sectors. jb noovf ;skip if below ; ; overflow to next track mov word ptr [bx],0 ; unasec = 0. inc word ptr unatrk ; unatrk = unatrk+1. ; noovf: ;match found, mark as unnecessary read mov rsflag,0 ;rsflag = 0 jmps rwoper ;to perform the write endif ; alloc: ;not an unallocater mov di,dma_off ;user buffer is dest if readop ; push DS push ES ;save segment registers ; mov ES,dma_seg ;set destseg to the users seg ;SI/DI and DS/ES is swapped ;if write op mov cx,128/2 ;length of move in words mov al,readop test al,al ;which way? jnz rwmove ;skip if read ; ; write operation, mark and switch direction mov hstwrt,1 ;hstwrt = 1 (dirty buffer now) xchg si,di ;source/dest index swap mov ax,DS mov ES,ax mov DS,dma_seg ;setup DS,ES forode,al ; save status bits. and al,0fdh ; look at error bits. jz wrtret ; none set, return from write. dec ercnt ; decrement retry counter. jnz wrthstrty ; if not zero retry write. mov al,2 ; write error flag. mov erflag,01h ; set error flag jmp recov ; go set error, return from write. ; set or clear write precompensation. precmp: push dx ; save dx and ax. push ax mov dx,ftrk ; get track register port. in al,dx ; read track register. cmp al,pctrk ; do we need ine return_hst: ret ; Call hard disk read routine. readh2: if nhard gt 0 ; if 1 or more hard disks. mov al,dmaread ; set read operation. hrdrw: mov byte ptr mwop,al mov cl,hstdsk ; get disk number. sub cl,8 ; make it hard disk drive no. jmp findalt ; do common read/write. endif ;************ HARD DISK DRIVER AREA ************************ if nhard gt 0 if mcmi19 ; if Morrow and CMI-19. include mw19 endif if mq540 ; if Morrow and Quantum Q540. inclu0 ; head position info for 8 floppies. ercnt db 0 ; counter for r/w retrys. sercnt db 0 ; counter for seek retrys. drvltr db 0 ; letter code for error printout. latch db 0 ; new code for latch. clatch db 0 ; current code in latch. iobyte db 0 ; system i/o redefinition byte. ercode db 0 ; last error result bits. msb20 db 0 ; dma abs bits a16-a19. lsb20 dw 0 ; dma abs bits a00-a15. ; Logical (letter) to physical (number) drive map. ; These should always stay in this order. T write ; rwmove: cld rep movs AX,AX ;move as 16 bit words pop ES pop DS ;restore segment registers ; ; data has been moved to/from host buffer cmp wrtype,wrdir ;write type to directory? mov al,erflag ;in case of errors jnz return_rw ;no further processing ; ; clear host buffer for directory write test al,al ;errors? jnz return_rw ;skip if so mov hstwrt,0 ;buffer written call writehst mov al,erflag return_rw: ret ; ;************************************************pre-compensation? mov al,clatch ; get current latch value. jc precno ; hop if not. or al,20h ; set bit 5. jmps precex ; write it out and exit. precno: and al,0dfh ; clear bit 5. precex: mov dx,fcont ; get latch port adr. out dx,al ; set the latch. mov clatch,al ; remember what's there. pop ax ; restore ax and dx. pop dx wrtret: ret ; Call Hard disk write routine. writeh: if nhard gt 0 ; if 1 or more hard disks. mov al,dmawrit ; set write operation. jmp hrdrw de mwq540 endif endif ;*********** END OF HARD DISK DRIVER AREA ****************** ; bios data area. data_offset equ (offset $) dseg org data_offset ; start of data segment area. ; loader & system messages. if loader ; start condition (loader_true). signon db cr,lf,'LDBIOS of 6-24-84',cr,lf,0 endif ; end condition (loader_true). if not loader ; start condition (loader_false). signon db cr,lf,'Duplex 816 BIOS of 6-24-84',cr,lf db '(c) 1984 Tarbell Electrono change ; the map, change the EQU's at the beginning of BIOS. drvmap db drivea ; drive a number. db driveb ; drive b number. db drivec ; drive c number. db drived ; drive d number. db drivee ; drive e number. db drivef ; drive f number. db driveg ; drive g number. db driveh ; drive h number. db drivei ; drive i number. db drivej ; drive j number. db drivek ; drive k number. db drivel ; drive l number. db drivem ; drive m number. db driven ; drive n***** ;* * ;* WRITEHST performs the physical write to the host * ;* disk, while READHST reads the physical disk. * ;* * ;***************************************************** ; ; write host routine - writes hsttrk,hstsec from hstbuf writehst: if not loader cmp hstdsk,8 ; is it a hard disk drive? jnc writeh ; hop if so. mov cx,hsttrk ; get track # mov dl,hstdsk ; get drive # call ; hard disk read/write. endif endif ; ; read host routine - reads hsttrk,hstsec to hstbuf ; readhst: cmp hstdsk,8 ; is it a hard disk drive? jnc readh2 ; hop if so. mov cx,hsttrk ; get track # mov dl,hstdsk ; get drive # call seekls ; seek disk to proper track mov dx,offset hstbuf ; get destination offset. mov ax,cs ; get destination segment. call comdma ; compute physical dma address. mov ercnt,rtcnt ; reset read retry error counter. rdhstrty: mov ax,hstsec ;ics',cr,lf db 'Support for:',cr,lf if nflop5 gt 0 db ' 5-inch diskettes',cr,lf endif if nflop8 gt 0 db ' 8-inch diskettes',cr,lf endif if nhard gt 0 if mcmi19 ; if morrow and CMI-19. db ' CMI-19 hard disk',cr,lf endif if mq540 ; if morrow and Quantum Q540. db ' Quantum Q-540 hard disk',cr,lf endif endif db cr,lf,'CP/M-86 vs 1.1',cr,lf db '(c) 1983 Digital Research',cr,lf,0 trpmsg db cr,lf,7 db 'BIOS detected undefined interrupt' db cr,lf,0 endif ; end co number. db driveo ; drive o number. db drivep ; drive p number. ; sek_dsk rb 1 ;seek disk number sek_trk rw 1 ;seek track number sek_sec rw 1 ;seek sector number ; hst_dsk rb 1 ;host disk number hst_trk rw 1 ;host track number hst_sec rw 1 ;host sector number ; sek_hst rw 1 ;seek shr secshf hst_act rb 1 ;host active flag hst_wrt rb 1 ;host written flag ; una_cnt rw 1 ;unalloc rec cnt una_dsk rb 1 ;last unalloc disk una_trk rw 1 ;last unalloc track una_sec rw 1 ;last un seekls ; seek disk to proper track call precmp ; set or clear pre-comp bit. mov dx,offset hstbuf ; get source offset. mov ax,cs ; get source segment. call comdma ; compute physical dma address. mov ercnt,rtcnt ; reset write retry error counter. wrthstrty: mov ax,hstsec ; get sector to write. inc ax ; make sectors start at 1. mov cx,0a0d0h ; floppy write, force interrupt cmds. mov dx,08200h ; dma write, dma count byte cmds. call dmarw ; go write the sector. mov erc get sector to read inc ax ; make sectors start at 1. mov cx,088d0h ; floppy read, force interupt cmds. mov dx,04200h ; dma read, dma count 512 bytes. call dmarw ; go read the sector. mov ercode,al ; save status bits. and al,09dh ; look at error bits. jz return_hst ; none set, return from read. dec ercnt ; decrement retry counter. jnz rdhstrty ; if not zero retry read. mov al,1 ; read error flag. mov erflag,01h ; set error flag jmp recov ; go to read recovery routnditions. errmsg db cr,lf db 'error during ',0 db 'seek: ',0 ; error 0. db 'read: ',0 ; error 1. db 'write:',0 ; error 2. drvmsg db ' drive ',0 db ', track ',0 db ', sector ',0 db ', status ',0 ; disk control storage. drvflg db 0,0,0,0,0,0,0,0 ; density info for 8 floppies. dens db 0 ; current drive density value. diskno dw 0 ; current disk number and zero byte. sect db 0 ; current real sector #. trk db 0 ; head position for selected drive. trtab db 0,0,0,0,0,0,0,dos to index the drive attrib info tables. dphtab dw (offset dph0) ; 5-inch floppy 0. dw (offset dph1) ; 5-inch floppy 1. dw (offset dph2) ; 5-inch floppy 2. dw (offset dph3) ; 5-inch floppy 3. dw (offset dph4) ; 8-inch floppy 0. dw (offset dph5) ; 8-inch floppy 1. dw (offset dph6) ; 8-inch floppy 2. dw (offset dph7) ; 8-inch floppy 3. if nhard gt 0 ; if 1 or more hard disks. dw (offset dph8) ; hard disk 0. endif if nhard gt 1 ; if 2 or more hard disks. dw (offset dp dph5 equ (offset $) if nflop8 gt 1 ; start condition (nflop>1_true). dw (offset xlt8),0000h ; translate table. dw 0000h,0000h ; scratch area. dw (offset dirbuf),0 ; dir buff, parm block. dw (offset csv5),(offset alv5) ; check, alloc vectors. endif ; end condition (nflop>1_true). ; - 8-inch floppy diskette - unit 2. dph6 equ (offset $) if nflop8 gt 2 ; start condition (nflop>2_true). dw (offset xlt8),0000h ; translate table. dw 0000h,0000h ; scratch area. Format 512 x 8 double density single sided floppy. f5i8ss db 00001101b ; format code. dw 0 ; no translate table. dw 32 ; 128-byte sectors per track. db 3 ; block shift factor. db 7 ; block mask. db 0 ; null mask. dw 155 ; disk size - 1. dw 63 ; directory max. db 11000000b ; alloc 0. db 0 ; alloc 1. dw 16 ; check size. dw 1 ; track offset. ; 5-inch IBM Format 512 x 8 double density double sided floppy. f5i8ds db 00001111b ; our internal format code. dw 0 ; no tradensity, double sided floppy diskette. f8sdds db 2 ; log byte - single density/double sided. dw (offset xlt8) ; use single density translate table. dw 0026 ; sectors/track. db 0004 ; block shift. db 0015 ; block mask. db 0000 ; extnt mask. dw 0242 ; disk size - 1. dw 0095 ; directory max. db 0192 ; alloc0. db 0000 ; alloc1. dw 0024 ; check size. dw 0002 ; number of system tracks. ; 8-inch double density, single sided floppy diskette. f8ddss db 1 ; log byte - doublh9) ; hard disk 1. endif if nhard gt 2 ; if 3 or more hard disks. dw (offset dph10) ; hard disk 2. endif if nhard gt 3 ; if 4 or more hard disks. dw (offset dph11) ; hard disk 3. endif if nhard gt 4 ; if 5 or more hard disks. dw (offset dph12) ; hard disk 4. endif if nhard gt 5 ; if 6 or more hard disks. dw (offset dph13) ; hard disk 5. endif if nhard gt 6 ; if 7 or more hard disks. dw (offset dph14) ; hard disk 6. endif if nhard gt 7 ; if 8 hard disks. dw (ofdw (offset dirbuf),0 ; dir buff, parm block. dw (offset csv6),(offset alv6) ; check, alloc vectors. endif ; end condition (nflop>2_true). ; - 8-inch floppy diskette - unit 3. dph7 equ (offset $) if nflop8 gt 3 ; start condition (nflop>3_true). dw (offset xlt8),0000h ; translate table. dw 0000h,0000h ; scratch area. dw (offset dirbuf),0 ; dir buff, parm block. dw (offset csv7),(offset alv7) ; check, alloc vectors. endif ; end condition (nflop>3_true). ; Disk Parnslate table. dw 32 ; 128-byte sectors per cylinder. db 4 ; block shift factor for 2k blocks. db 15 ; block mask for 2k blocks. db 1 ; null mask. dw 009dh ; disk size - 1. dw 63 ; directory max. db 10000000b ; alloc 0. db 0 ; alloc 1. dw 16 ; check size. dw 1 ; track offset. ; 5-inch 512 x 10 double density single sided floppy. f5dbss db 5 ; format code. dw 0 ; no translate table. dw 40 ; sectors per track. db 4 ; block shift factor. db 15 ; block mask. db e density/single sided. dw 0000 ; no sector translate table. dw 0051 ; 51 sectors. db 0004 ; block shift. db 0015 ; block mask. db 0000 ; extnt mask. dw 0237 ; disk size - 1. dw 0127 ; directory max. db 0192 ; alloc0. db 0000 ; alloc1. dw 0032 ; check size. dw 0002 ; number of system tracks. ; 8-inch double density, double sided floppy diskette. f8ddds db 3 ; log byte - double density/sided sided. dw 0000 ; no sector translate table. dw 0051 ; 51 sectors. dfset dph15) ; hard disk 7. endif ; - 5-inch floppy diskette - unit 0. dph0 equ (offset $) if nflop5 gt 0 dw (offset xlt5),0 dw 0,0 dw (offset dirbuf),0 dw (offset csv0),(offset alv0) endif ; 5-inch floppy unit 1. dph1 equ (offset $) if nflop5 gt 1 dw (offset xlt5),0 dw 0,0 dw (offset dirbuf),0 dw (offset csv1),(offset alv1) endif ; 5-inch floppy unit 2. dph2 equ (offset $) if nflop5 gt 2 dw (offset xlt5),0 dw 0,0 dw (offset dirbuf),0 dw (offsetameter Blocks (DPB's). ; these tables define the drive physical attributes. ; 5-inch table of disk parameter block addresses. dpbt5 equ (offset $) if nflop5 gt 0 db 0feh ; ibm code for ss 8-sector. dw offset f5i8ss db 0ffh ; ibm code for ds 8-sector. dw offset f5i8ds db 0deh ; 512 deblocked single sided. dw (offset f5dbss) db 0dch ; 512 deblocked double sided. dw (offset f5dbds) db 00h ; default to sd ss. dw (offset f5sdss) endif ; 8-inch table of disk parame0 ; null mask. dw 94 ; disk size-1. dw 81 ; directory max. db 11000000b ; alloc 0. db 0 ; alloc 1. dw 32 ; check size. dw 2 ; track offset. ; 5-inch 512 x 10 double density, double sided floppy. f5dbds db 7 ; format code. dw 0 ; no translate table. dw 40 ; sectors per track. db 5 ; block shift factor. db 31 ; block mask. db 0 ; extent mask. dw 94 ; disk size - 1. dw 81 ; directory max. db 11000000b ; alloc 0. db 0 ; alloc 1. dw 32 ; check size. dw 2 b 0005 ; block shift. db 0031 ; block mask. db 0000 ; extnt mask. dw 0237 ; disk size - 1. dw 0095 ; directory max. db 0192 ; alloc0. db 0000 ; alloc1. dw 0024 ; check size. dw 0002 ; number of system tracks. ; 8-inch 512 x 16 single sided diskette. f8dbss db 5 ; log byte - 512 x 16 single sided dw 0000 ; no sector translate table. dw 0064 ; 64 - 128 byte sectors. db 0004 ; block shift. db 0015 ; block mask. db 0000 ; extnt mask. dw 0299 ; disk size - 1. csv2),(offset alv2) endif ; 5-inch floppy unit 3. dph3 equ (offset $) if nflop5 gt 3 dw (offset xlt5),0 dw 0,0 dw (offset dirbuf),0 dw (offset csv3),(offset alv3) endif ; - 8-inch floppy diskette - unit 0. dph4 equ (offset $) if nflop8 gt 0 dw (offset xlt8),0000h ; translate table. dw 0000h,0000h ; scratch area. dw (offset dirbuf),0 ; dir buff, parm block. dw (offset csv4),(offset alv4) ; check, alloc vectors. endif ; - 8-inch floppy diskette - unit 1.ter block addresses. dpbt8 equ (offset $) if nflop8 gt 0 db 0e7h ; single density double sided. dw (offset f8sdds) db 0ddh ; double density single sided. dw (offset f8ddss) db 0dfh ; double density double sided. dw (offset f8ddds) db 0deh ; 512 deblocked single sided. dw (offset f8dbss) db 0dch ; 512 deblocked double sided. dw (offset f8dbds) db 00h ; default to sd ss. dw (offset f8sdss) endif if nflop5 gt 0 ; 5-inch disk parameter blocks. ; 5-inch IBM; track offset. ; 5-inch 128 x 18 single density, single sided floppy. f5sdss db 0 ; format code. dw offset xlt5 ; translate table. dw 18 ; sectors per track. db 3 ; block shift factor. db 7 ; block mask. db 0 ; null mask. dw 71 ; disk size - 1. dw 63 ; directory max. db 11000000b ; alloc 0. db 0 ; alloc 1. dw 16 ; check size. dw 3 ; track offset. endif ; end of 5-inch disk parameter blocks. if nflop8 gt 0 ; 8-inch disk parameter blocks. ; 8-inch single ; number of system tracks. ; 8-inch single density, single sided floppy diskette. f8sdss db 0 ; log byte - single density/single sided. dw (offset xlt8) ; use single density translate table. dw 0026 ; sectors/track. db 0003 ; block shift. db 0007 ; block mask. db 0000 ; extnt mask. dw 0242 ; disk size - 1. dw 0063 ; directory max. db 0192 ; alloc0. db 0000 ; alloc1. dw 0016 ; check size. dw 0002 ; number of system tracks. endif ; end of 8-inch disk parameter blor interrupt vector ini info. int0_offset rw 1 ; interrupt offset address. int0_segment rw 1 ; interrupt segment address. rw 2*(bdos_int-1) ; pad to the system entry vector. bdos_offset rw 1 ; bdos offset address. bdos_segment rw 1 ; bdos segment address. ; end db 0 ; fill to last for gencmd. ; assign external address locations. dseg 0 ; obtain absolute low memory. org 0 ; f title 'CCP/M-86 Loader of 9-17-84' ; Last changed 9-17-84 by Don Tarbell. ; Note: This is adaptation of the LDCPM module for CP/M-86. ; ; The CPMLDR consists of this module along with the ; LDRBDOS and LBIOS. ; CPMLDR resides on the first two tracks of a ; CCP/M-86 system diskette and is brought into memory ; by the ROM bootstrap loader to load initiate CCP/M-86 ; It opens the file 'CPM.SYS' using the LDRBDOS and LBIOS ; and then reads it into memory. Finally, a jump to the BIOS ; initialibdos_segment,cs ; offset and segment mov ax,cs ! mov ss,ax ; make ss, ds, es = cs mov ds,ax ! mov es,ax mov sp,offset(stack) ; set up local stack call initlbdos ;warm up lbdos and lbios call openfnc ;open CPM.SYS cmp al,255 ! jne perr ; insure good file mov dx,offset nofile ! call msg ; no CPM.SYS file jmp stop ; then halt the machine perr: mov dx,cs ! call setdmab mov dx,offset page1 ! call setdma ;read first page of CPM.SYS call read mov ax,word ptr page1+3 ocks. ; provide sector translation for single density access. ; 5-inch if nflop5 gt 0 xlt5 db 1,4,7,10,13,16 db 2,5,8,11,14,17 db 3,6,9,12,15,18 endif ; 8-inch if nflop8 gt 0 xlt8 db 01,07,13,19,25,05 db 11,17,23,03,09,15 db 21,02,08,14,20,26 db 06,12,18,24,04,10 db 16,22 endif als5 equ 39 ; 5-inch allocation vector size. css5 equ 42 ; 5-inch check vector size. als8 equ 39 ; 8-inch allocation vector size. css8 equ 42 ; 8-inch check vector size. ; Buffersееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееzation entry point starts CCP/M-86 ; The first 128 byte record of the CPM.SYS file is a header ; with the following format: ; ty rb 1 ;seg type (not used here) ; len rw 1 ;length (not used here) ; abs dw ldrstart ;absolute segment address for LOADER ; min rw 1 ;minimum mem (not used here) ; max rw 1 ;max mem needed (not used here) ; (This header record is constructed automatically by the ; GENCMD utility). ; CPMLDR may be read into any segment that does not ; overlap the desired syste ;get abs field from header mov curseg,ax ; set starting segment. mov ldseg,ax ; save it and mov dx,ax ! call setdmab ; set DMA segment for disk IO mov dx,offset segment ! call msg ; put memory map on console mov ax,ldseg ! call phex ; print base system segment ; mov dx,0 ;offset of CPM in segment readit: call setdma ; set DMA offset for push dx ! call read ; next sector read cmp al,01H ! je done ; check for EOF cmp al,0 ! je prerr ; check for good write mov. dirbuf rs hstsiz ; (128) directory buffer. hstbuf rb hstsiz ; host buffer chkbuf rb chksiz ; buffer to check disk density code. if nflop5 gt 0 alv0 rs als5 csv0 rs css5 endif if nflop5 gt 1 alv1 rs als5 csv1 rs css5 endif if nflop5 gt 2 alv2 rs als5 csv2 rs css5 endif if nflop5 gt 3 alv3 rs als5 csv3 rs css5 endif if nflop8 gt 0 alv4 rs als8 csv4 rs css8 endif if nflop8 gt 1 alv5 rs als8 csv5 rs css8 endif if nflop8 gt 2 alv6 rs als8 csv6 rs csееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееm load segment as it makes ; all memory references using copies of the CS: register ; it is entered with. false equ 0 true equ not false cr equ 0dh lf equ 0ah lbios_offset equ 1200h ; offset of LBIOS bootdrv equ 0 ; boot drive always zero ; 128 bytes of CPM.SYS lbdosoff equ 406H ;location of LBDOS in LOADER bdos_int equ 224 ;lbdos interrupt number ; dummy section for interrupt vectors dseg 0 org 0 abs_zero rw 2*bdosint bdos_offset rw 1 bdos_segment rw dx,offset rerr ! call msg ; print READ ERROR message jmp stop ; hard stop on any error prerr: pop dx ! add dx,80h ; address for next record cmp dx,0 ; has offset wrapped around? jne readit ; loop back if not. ; note: this code works on the assumption that we started on an ; even 128-byte (80h) boundry. add curseg,1000h ; increment current segment. mov dx,curseg ; set new segment in system. call setdmab mov dx,0 ; start at zero offset. jmp readit done: mov ds8 endif if nflop8 gt 3 alv7 rs als8 csv7 rs css8 endif locstk rw 32 ; local stack for ini. stkbase equ (offset $) ; define stack base address. lastoff equ (offset $) ; last used area address. tpaseg equ (lastoff+0400h+15) / 16 tpalen equ 0800h - tpaseg ; compute start and length of main tpa. tpaoff equ tpaseg ; offset in paragraphs to end of cp/m-86. db 0 ; fill to last for gencmd. ; assign external address locations. dseg 0 ; obtain absolute low memory. org 0 ; fееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее1 ; bdos function numbers coutf equ 2 pstrf equ 9 seldsk equ 14 openf equ 15 readsf equ 20 dmaf equ 26 dmabf equ 51 ;******************************* ;* ;* CPMLDR starts here ;* ;******************************* cseg org 0 ; JMPF to here from boot ROM jmp LBIOS ; allow loader BIOS to ; initialize start: ; loader BIOS jumps here xor ax,ax ! mov ds,ax ; temp DS at absolute zero mov bdos_offset,lbdosoff ; to patch in interrupt table mov l pnib ; print hex nibble pop ax ! pop cx ; restore registers dec ch ! jnz lhex ; and loop four times ret pnib: ;print low nibble in AL as hex char and al,0fh ! cmp al,9 ja p10 ;above 9 ? add al,'0' ;digit jmp prn p10: add al,'A'-10 ;char a-e prn: mov dl,al ;****** putchar: mov cl,coutf jmp sys_vec ;****** initlbdos: mov cl,seldsk ! mov dx,bootdrv ; select boot disk jmp sys_vec ;****** openfnc: mov cl,openf ! mov dx,offset fcb ; fcb already initialized mov ; *********** BEGINNING OF CMI CM5619 HARD DISK EQU's ***************** ; CMI CM5619 Equates for CP/M-80, CP/M-86, and Concurrent CP/M-86. ; Created 10-15-85 by Don Tarbell. ; Changes by Don Tarbell: ; 11-05-85: made Otari C-526 version from Quantum 540 version. ; 12-03-85: made CMI CM5619 version from Otari C-526 version. ; 12-05-85: moved Disk Parameter Blocks to Z816BIOS.A86. ; Equates. nlp equ 2 ; logical drives for 1 physical drive. cyl equ 306 ; number of cylinders. heads e; *********** BEGINNING OF Rodime 20 HARD DISK EQU's ***************** ; Equates for CP/M-80, CP/M-86, and Concurrent CP/M-86. ; Created 10-15-85 by Don Tarbell. ; Changes by Don Tarbell: ; 11-05-85: made Otari C-526 version from Quantum 540 version. ; 12-03-85: made CMI CM5619 version from Otari C-526 version. ; 12-05-85: made Rodime-20 version from CMI CM5619 version. ; Equates. nlp equ 2 ; logical drives for 1 physical drive. cyl equ 320 ; number of cylinders. heads equ 6 ; n; *********** BEGINNING OF FUJITSU 4695 HARD DISK EQU's ***************** ; Hard Disk Equates for CP/M-80, CP/M-86, and CCP/M-86. ; Created 10-15-85 by Don Tarbell. ; Changes by Don Tarbell: ; 11-05-85: made Otari C-526 version from Quantum 540 version. ; 12-05-85: moved Disk Parameter Blocks to BIOS module. ; 12-05-85: made Fujitsu 4695 version from Otari C-526 version. ; Equates. nlp equ 3 ; logical drives per physical drive. cyl equ 320 ; number of cylinders. heads equ 8 ; nucl,openf jmp sys_vec ;******** ; setdma: ;set new dma addr in dx mov cl,dmaf jmp sys_vec ;******** ; setdmab: ; set new dma segment base from DX mov cl,dmabf jmp sys_vec ;****** ; pcrlf: mov dx,offset crlf ;print carriage return, line feed ;****** ; msg: ;print msg starting at dx until $ mov cl,pstrf ;print string function jmp sys_vec ;***** ; read: mov dx,offset fcb ! mov cl,readsf ; jmp sys_vec ;****** ; sys_vec: int bdos_int ret ;****** ; qu 6 ; number of heads. precomp equ 128 ; cylinder to start write precompensatin. lowcurr equ 128 ; cylinder to start low current. stepdly equ 2 ; step delay. steprcl equ 60 ; recalibrate step delay. if teletek ; if teletek controller. hrdspt equ 16 ; sectors per track. headdly equ 1 ; settle delay (0-25.5 microsec.) hdsm0 equ 2047 ; logical disk 0 size minus one. hdir0 equ 2047 ; disk 0 directory size minus one. hdsm1 equ 1608 ; logical disk 1 size minus one. hdir1 equ 1608 ; diumber of heads. precomp equ 0 ; cylinder to start write precompensatin. lowcurr equ 132 ; cylinder to start low current. stepdly equ 0 ; step delay. steprcl equ 30 ; recalibrate step delay. if teletek ; if teletek controller. hrdspt equ 16 ; sectors per track. headdly equ 1 ; settle delay (0-25.5 microsec.) hdsm0 equ 2047 ; logical disk 0 size minus one. hdir0 equ 2047 ; disk 0 directory size minus one. hdsm1 equ 1775 ; logical disk 1 size minus one. hdir1 equ 1775 ; disk 1 directmber of heads. precomp equ 160 ; cylinder to start write precompensatin. lowcurr equ 160 ; cylinder to start low current. stepdly equ 0 ; step delay. steprcl equ 30 ; recalibrate step delay. if teletek ; if teletek controller. hrdspt equ 16 ; sectors per track. headdly equ 1 ; settle delay (0-25.5 microsec.) hdsm0 equ 2047 ; logical disk 0 size minus one. hdir0 equ 2047 ; disk 0 directory size minus one. hdsm1 equ 2047 ; logical disk 1 size minus one. hdir1 equ 2047 ; disk 1 direcstop: hlt ; hard stop 8086 for error jmp stop ;******************************** ;* ;* DATA AREA ;* ;******************************** nofile db cr,lf,'The File CCPM.SYS Not Found On This Disk$' rerr db cr,lf,'Error In Reading CCPM.SYS$' segment db cr,lf,'Segment Address = $' lenmsg db cr,lf,' Last Offset = $' crlf db cr,lf,'$' ; vector for jmpf indirect to start CCP/M curseg rw 1 ; current segment loading. ccpm dd abs_zero ; (dummy value) org offset ccpm ; overlsk 1 directory size minus one. offset0 equ 1 ; first track of logical drive 0. offset1 equ 172 ; first track of logical drive 1. endif if morrow ; if morrow controller. hrdspt equ 17 ; sectors per track. headdly equ 0 ; head settle delay. hdsm0 equ 2047 ; logical disk 0 size minus one. hdir0 equ 2047 ; logical disk 0 directory max. hdsm1 equ 1835 ; logical disk 1 size minus one. hdir1 equ 1835 ; logical disk 1 directory max. offset0 equ 1 ; first track of logical drive 0. offset1 eory size minus one. offset0 equ 1 ; first track of logical drive 0. offset1 equ 172 ; first track of logical drive 1. endif if morrow ; if morrow controller. hrdspt equ 17 ; sectors per track. headdly equ 0 ; head settle delay. hdsm0 equ 2047 ; logical disk 0 size minus one. hdir0 equ 2047 ; logical disk 0 directory max. hdsm1 equ 2013 ; logical disk 1 size minus one. hdir1 equ 2013 ; logical disk 1 directory max. offset0 equ 1 ; first track of logical drive 0. offset1 equ 162 ; ftory size minus one. hdsm2 equ 1007 ; logical disk 2 size minus one. hdir2 equ 1007 ; disk 2 directory size minus one. offset0 equ 1 ; first track of logical drive 0. offset1 equ 129 ; first track of logical drive 1. offset2 equ 257 ; first track of logical drive 2. endif if morrow ; if morrow controller. hrdspt equ 17 ; sectors per track. headdly equ 0 ; head settle delay. hdsm0 equ 2047 ; logical disk 0 size minus one. hdir0 equ 2047 ; logical disk 0 directory max. hdsm1 equ 2047ay preceding with DW's ccpmstart dw 0 ; zero offset into ccpm. ldseg rw 1 ; second is segment to put CCPM.SYS fcb db 0,'CCPM ','SYS',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 org (offset $+1) and 0FFFEh ; even address for stack rw 32 stack equ offset $ dseg org stack page1 rb 128 ; dummy section for BIOS init label org lbios_offset lbios: end qu 162 ; first track of logical drive 1. endif cpmspc equ heads * hrdspt * 4 ; 128-byte sectors per cylinder. ; ********** END OF CMI CM5619 SPECIFIC CODE ********************* dsm0 equ 2047 ; logical disk 0 size minus one. hdir0 equ 2047 ; logical disk 0 directory max. hdsm1 equ 1835 ; logical disk 1 size minus one. hdir1 equ 1835 ; logical disk 1 directory max. offset0 equ 1 ; first track of logical drive 0. offset1 eirst track of logical drive 1. endif cpmspc equ heads * hrdspt * 4 ; 128-byte sectors per cylinder. ; ********** END OF Rodime 20 SPECIFIC CODE ********************* 47 ; logical disk 0 size minus one. hdir0 equ 2047 ; logical disk 0 directory max. hdsm1 equ 2013 ; logical disk 1 size minus one. hdir1 equ 2013 ; logical disk 1 directory max. offset0 equ 1 ; first track of logical drive 0. offset1 equ 162 ; f ; *********** BEGINNING OF ATASI-33 HARD DISK EQU'S *********** ; Atasi-33 Hard Disk Equ's for CP/M-80, CP/M-86, and CCP/M-86. ; This module is normally used as an INCLUDE file for ASM-86. ; Changes by Don Tarbell: ; 8-13-85: separated equ's from hard disk controller driver. ; 8-18-85: added more parameters for more parameter blocks. ; 12-05-85: added different parameters for Morrow or Teletek. ; Hard disk drive equates. nlp equ 4 ; number of logical/physical drives. cyl equ 645 rive 2. offset3 equ 580 ; first track of logical drive 3. endif ; ********* END OF ATASI-33 HARD DISK EQU's *************************** y size minus one. hdsm3 equ 689 ; disk 3 size minus one. hdir3 equ 689 ; disk 3 directory size minus one. offset0 equ 1 ; first track of logical drive 0. offset1 equ 194 ; first track of logical drive 1. offset2 equ 387 ; first track of logical d; ************ TELETEK HARD DISK CONTROLLER DRIVER ***************** ; I/O Drivers for Teletek HDC FOR CONCURRENT CP/M-86 ONLY. ; Changes by Don Tarbell: ; 03-31-85: derived from bios of 12-9-84. ; 07-05-85: changed hrd2 equ to nlp equ. ; 10-09-85: derived from CP/M-86 version. ; 10-14-85: put in flag to not log in same drive more than once. ; 10-21-85: fixed overfl