;---------------------------------------------------------------- ; This is SME Systems PL/I General Purpose Utility Module ; ; This module links to the PL/I-80 main module and provides the ; following facilities ; ; GETDPB Read the DPB into a PL/I structure ; SETDSK Select a disk ; SETTRK Set the track up for I/O ; SETSEC Set the sector up for I/O ; SETDMA Set up DMA for I/O ; GETSEC Read a sector ; PUTSEC Write a sector ; GETVER Get CP/M Version ; SETERM Set error mode to return values to the program ; LOGDSK Log in a disk via the Bdos ; RESSYS Reset the disk system ; ; CONST Get console status ; CONIN Fetch a character ; CAPS Capitalize a character ; DELAY Delay a number of mS ; ; Written by Richard Holmes 25-09-84 ; Last Update Richard Holmes 14-12-84 ;---------------------------------------------------------------- ; name 'PLIUTIL' ; public getdpb,setdsk,settrk,seterm public setsec,setdma,getsec,putsec public sectrn,getver,logdsk,ressys ; public const,conin,caps extrn getp1,getp2,?ver ; maclib z80 ; bdos equ 5 ccp equ 0 dircon equ 6 sysres equ 13 ; Reset disk system retver equ 12 ; Get version number (HL) rread equ 13 ; Bios random read rwrite equ 14 ; Bios random write seldsk equ 14 ; Select disk (E) curdsk equ 25 ; Current disk (A) getadr equ 31 ; Get DPB Address (HL) resdrv equ 37 ; Reset drive (DE) getscb equ 49 ; Get/Set SCB biosfn equ 50 ; Direct bios calls ; ressys: mvi c,sysres call bdos ret ; logdsk: call clr$table ; Clear the bios table area call getp1 mov a,e sui 'A' ; Make into a drive code cpi 16 jnc sd$err1 ; No carry and an error mov e,a ; Re-load the disk code mvi c,14 ; LOG bdos call call bdos ret ; putsec: call clr$table mvi a,rwrite ; Sector set BIOS code call do$bios ; Do the bios call ; Return the bios function code to PL/I mov l,a mvi h,0 ; 00 return = error ret ; ;---------------------------------------- ; Console Status. Bit 1 true = keypressed ;---------------------------------------- ; const: mvi c,11 call bdos ora a rz mvi a,0ffh mov l,a ret ; ;-------------- ; Console input ;-------------- ; conin: mvi c,1 call bdos jmp caps$exit ; return accumulator on stack ; ;------------------------ ; Capitalize the char(1); ;------------------------ ; caps: call getp1 mov a,e cpi 'a' jc caps$exit cpi 'z' + 1 jnc caps$exit ani 05fh caps$exit: pop h push psw inx sp mvi a,1 ; 1 character pchl ; ;------------------------------- ; Delay a number of milliseconds ;------------------------------- ; delay: call getp2 delms: call delms3 dcx d mov a,d ora e ; wait for d=e=0 jrnz delms ret ; ; Delay exactly 1 millisecond ; delms3: push b mvi b,230 delms4: nop djnz delms4 lxi b,00 pop b ret ; ;------------------------- ; Load a byte into the SCB ;------------------------- ; seterm: mvi a,04bh sta scb ; Offset to the byte to be set mvi a,0ffh sta scb + 2 ; Value to load mvi a,0feh ; Set a byte only sta scb + 1 lxi d,scb mvi c,49 call bdos ret ; scb: db 00 ; offset db 00 ; type of use dw 00 ; Value to load ; ;---------------------------------------------------------------- ; READ the sector as set up previously ;---------------------------------------------------------------- ; getsec: call clr$table mvi a,rread ; Sector set BIOS code call do$bios ; Do the bios call ; Return the bios function code to PL/I mov l,a ; Get a copy mvi h,0 ; 00 return = error ret ; ;---------------------------------------------------------------- ; Set the Track given into the BIOS of CP/M ;---------------------------------------------------------------- ; setsec: call getp2 ; fetch sector number sded creg mvi a,11 ; Track set BIOS code call do$bios ; Do the bios call ret ; ;---------------------------------------------------------------- ; Translate the sector from logical to physical ;---------------------------------------------------------------- ; sectrn: call clr$table ; Clear the function table call ld$block lhld p1 ; Fetch sector number mov e,m inx h mov d,m sded creg ; Save in BC lhld p2 mov e,m inx h mov d,m sded ereg ; Translate table address mvi a,16 ; Translate BIOS code call do$bios ; Do the bios call mov a,l ; HL returned with sector # ret ; ;---------------------------------------------------------------- ; Set the DMA address given into the BIOS of CP/M ;---------------------------------------------------------------- ; setdma: call getp2 ; fetch the POINTER sded creg mvi a,12 ; DMA address set code call do$bios ; Do the bios call ret ; ;---------------------------------| ; Set the DISK given into the BIOS| ;---------------------------------| ; setdsk: call clr$table ; Clear the bios table area call getp1 mov a,e sui 'A' ; Make into a drive code cpi 16 jnc sd$err1 ; No carry and an error sta creg ; save disk number ; mvi a,09 ; DISK set BIOS code call do$bios ; Do the bios call ; Return the XLT address to PL/I mov e,m inx h mov d,m xchg ; HL -> sector translate table now mov a,l ret sd$err1: lxi h,0 mov a,l ret ; ;---------------------------------------------------------------- ; Set the TRACK given into the BIOS of CP/M ;---------------------------------------------------------------- ; settrk: call getp2 ; fetch track number sded creg mvi a,10 ; TRACK set BIOS code call do$bios ; Do the bios call ret ; ;---------------------------------------------------------------- ; Return the CP/M version number. ; ; call getver(version); /* dcl version bin(15) */ ;---------------------------------------------------------------- ; getver: mvi c,retver call bdos mov a,l sta ?ver ; save version info for later ret ; ;---------------------------------------------------------------- ; Get the DPB into a structure ; ; status = getdpb(addr(dpb),drive); ;---------------------------------------------------------------- ; getdpb: call ld$block ; get all parameter addresses lhld p2 mov a,m ; fetch drive asked for sui 'A' ; Make into a drive code cpi 16 jnc dpb$err1 ; No carry and an error ; mov e,a mvi c,seldsk call bdos ; Test for select error ora a ; No error code if 00 jnz dpb$err2 ; mvi c,getadr call bdos ; If FFFF then not possible to get it mov a,l cpi 0ffh jnz get$dpb1 mov a,h cpi 0ffh jz dpb$err3 get$dpb1: push h lhld p1 ; PLI structure POINTER mov e,m inx h mov d,m pop h ; lxi b,17 ldir lxi h,0 ; return a zero ok flag ret ; dpb$err1: lxi h,1 mov a,l ret ; dpb$err2: lxi h,2 mov a,l ret ; dpb$err3: lxi h,3 mov a,l ret ; ; ;---------------------------------------------------------------- ; This utility subroutine must load the parameter block with the ; addresses of the parameters. HL -> parameter block. on entry ;---------------------------------------------------------------- ; ld$block: lxi d,block lxi b,8 ; 4 addresses ldir ret ; ; Clear the function table ; clr$table: push h push d push b lxi h,funct mvi m,00 lxi d,funct + 1 lxi b,7 ldir ; Clear it pop b pop d pop h ret ; ; Do the bios function call passed in register A ; do$bios: sta funct mvi c,biosfn ; Function code to call bios lxi d,funct ; Point to the start of the table call bdos ret ; ; Data variables / flag storage next ; dseg ; ; Bios calling storage facilities funct: db 00 areg db 00 creg db 00 breg db 00 ereg db 00 dreg db 00 lreg db 00 hreg db 00 ; ; ; ; The following is filled in so that the address point to parameters ; in the program ; block: p1: dw p1 ; address of parameter 1 p2: dw p2 ; address of parameter 2 p3: dw p3 ; address of parameter 3 p4: dw p4 ; address of parameter 4 ; ; end