ingoldsby@calgary.UUCP (Terry Ingoldsby) (05/27/86)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % The following is a modified (debugged) version of the % % Color Computer OS9 Disk Driver by Dave Lewis. The % % modifications were made by Terrance Ingoldsby in May % % of 1986 and he accepts the credit or blame associated % % with the mods. Enjoy. P.S. Thanks Dave! % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% From: dml@loral.UUCP (Dave Lewis) ------------------------------- Before I am buried in E-mail (short pause to spit out some stray bits) here is NewDisk. Assemble this source using the Microware OS-9 assembler. Ensure that the files OS9Defs, RBFDefs, SCFDefs and DEFSFile are present in the DEFS directory (DEFSFile says essentially, USE OS9Defs, USE RBFDefs, USE SCFDefs, USE SYSType) SYSType is not necessary because NewDisk doesn't reference any of the symbols defined there. Invoke it as: asm newdisk o=newdisk.obj #16k Then the fun begins. You must remove the existing CCDisk module from your OS9Boot file and insert NewDisk. This means making a new system disk. BIG PROBLEM: The system disk must be single-sided. OS9Gen and Cobbler are both unable to cope with double-sided disks. If you make one, OS-9 won't mind but YOU CAN'T BOOT IT UP. This is obviously a major problem, and it severely limits the usefulness of the NewDisk module. I'm rewriting OS9Gen to automatically handle both single and double sided disks. It's Friday now and I hope to have it done by Monday. I hoped to have it done by last Monday, too. Despite this, NewDisk can and will read just about any format once installed. If you set up all your disks as 35-track single siders and stick in a 40-track double, NewDisk will happily read and write it all day long. The only limit is the performance of your disk drives. I run a system with /D0 = 40T DS, /D1 and /D2 = 80T DS. Total storage: 1.8 Megabytes. I recommend that even after you have double-sided boot disks, you keep one 35-track single sided system master around for compatibility. It won't limit your system's performance but it is certain to run on ANYTHING. Also, your disk descriptors will control how your disks get formatted. If the descriptor says single-sided, you will format single-sided disks in that drive. You may choose to use different descriptors on your drives so you can format disks several ways without rebooting or using Debug. Over the next several days I will be posting a disk descriptor, improved Dump utility, 80-column directory command, and reposting Separate, my bootfile breaking utility. I'm pleased to see all the interest out there. It tells me OS-9 is alive and well, despite (or is it because of) its `lack' of me-too IBM compatability. And now, a word from the sponsor. If anyone out there likes these programs enough, some $$$ would be much appreciated. I think NewDisk is worth about $5, the others less because I put less work into them. (Dump took about 5 hours) For $10 I'll send a disk with all the programs mentioned here, plus some procedure files and documentation for installing them on several different system configurations. If you think your system is really unique, tell me what you've got and I'll make sure it's covered. And now ... heeeeere's NewDisk!! (groan) ------------------------------- Dave Lewis Loral Instrumentation San Diego sdcc6 ---\ gould9 --\ ihnp4 ---->-->!sdcc3 ---->--->!loral!dml (uucp) sdcrdcf -/ sdcsvax -/ Stupidity got us into this mess -- why can't it get us out of it? ------------------------------- % Remove everything above and including this line for assembly % NAM NewDisk TTL Improved OS-9 disk device driver module * * Copyright 1985 by Dave Lewis * 4417 Idaho apt. 4 * San Diego, CA 92116 * Released to public domain January, 1986 * IFP1 USE /D0/DEFS/DEFSFile ENDC * REV EQU 1 TYPE EQU DRIVR+OBJCT ATTR EQU REENT+REV * N.DRIVES EQU 3 Number of drives supported DISKRUN EQU $70 Disk run time after access NMIVECT EQU $109 NMI jump vector in RAM COMDREG EQU $FF48 1793 Command register (write) STATREG EQU $FF48 1793 Status register (read) TRAKREG EQU $FF49 1793 Track register SECTREG EQU $FF4A 1793 Sector register DATAREG EQU $FF4B 1793 Data register * MOD SIZE,NAME,TYPE,ATTR,EXEC,STORG FCB $FF Mode byte -- all modes NAME FCS 'CCDisk' Still the same module name FCB 4 Version number * RMB DRVBEG Storage common to all drives TABL.ORG RMB DRVMEM Drive 0 parameter table RMB DRVMEM Drive 1 parameter table RMB DRVMEM Drive 2 parameter table DRV.ACT RMB 2 Active drive's table origin DPRT.IMG RMB 1 Drive control port image byte DRVS.RDY RMB 1 Drive ready flags Q.SEEK RMB 1 Same drive/track flag STORG EQU . Total storage required * * Function dispatch vectors * EXEC LBRA INIT Initialize variables LBRA READ Read one sector LBRA WRITE Write one sector LBRA RETNOERR GETSTA call is not used LBRA SETSTA Two oddball calls LBRA RETNOERR TERM call is not used * INIT CLR >D.DSKTMR Zero disk rundown timer LDA #$D0 `Force interrupt' command STA >COMDREG LDA #$FF LDB #N.DRIVES Number of drives STB V.NDRV,U LEAX TABL.ORG,U Origin of first drive table INI.TBL STA DD.TOT+1,X Make total sectors nonzero STA V.TRAK,X Force first seek to track 0 CLR DD.FMT,X Make it see a 1-sided disk LEAX DRVMEM,X Go to next drive table DECB Test for last table done BNE INI.TBL Loop if not finished LEAX NMI.SVC,PCR Get address of NMI routine STX >NMIVECT+1 NMI Jump vector operand LDA #$7E Jump opcode STA >NMIVECT NMI Jump vector opcode LDA >STATREG Clear interrupt condition RETNOERR CLRB RTS * ERR.WPRT COMB Set carry flag LDB #E$WP Set error code RTS ERR.SEEK COMB Set carry flag LDB #E$SEEK Set error code RTS ERR.CRC COMB Set carry flag LDB #E$CRC Set error code RTS ERR.READ COMB Set carry flag LDB #E$READ Set error code RTS * * All disk controller commands exit via NMI. The service routine * returns control to the address on top of stack after registers * have been dumped off. * NMI.SVC LEAS R$SIZE,S Dump registers off stack LDA >STATREG Get status condition STAT.TST LSLA Test status register bit 7 LBCS ERR.NRDY Status = Not Ready if set LSLA Test bit 6 BCS ERR.WPRT Status = Write Protect if set LSLA Test bit 5 LBCS ERR.WRT Status = Write Fault if set LSLA Test bit 4 BCS ERR.SEEK Status = Record Not Found LSLA Test bit 3 BCS ERR.CRC Status = CRC Error if set LSLA Test bit 2 BCS ERR.READ Status = Lost Data if set CLRB No error if all 0 RETURN1 RTS * READ TSTB If LSN is greater than 65,536 BNE ERR.SECT return a sector error LDA #$A4 Set retry control byte CMPX #0 Is it sector 0? BNE READ2 If not, just read the data BSR READ2 If sector 0, read it and BCS RETURN1 update drive table PSHS Y,X Save X and Y LDX PD.BUF,Y Point to data buffer LDY DRV.ACT,U Point to active drive's table LDB #DD.RES+1 Counter and offset pointer SEC0LOOP LDA B,X Get byte from buffer STA B,Y Store in drive table DECB Decrement loop index BPL SEC0LOOP Loop until B < 0 CLRB No error PULS X,Y,PC Pull and return * WRITE TSTB If LSN is greater than 65,536 BNE ERR.SECT return a sector error LDA #$A4 Set retry control byte PSHS X,A,CC Save registers LBSR DSKSTART Start and select drive BCS EXIT.ERR Exit if error REWRITE LDX 2,S Get LSN off stack LBSR SEEK Position head at sector BCS RETRY.WR Try again if seek error BSR WRITE2 Write the sector BCS RETRY.WR Try again if write error TST PD.VFY,Y Check verify flag BNE EXIT.NER Exit without verify if off BSR VERIFY Verify sector just written BCC EXIT.NER Exit if no error RETRY.WR LDA 1,S Get retry control byte LSRA Indicate another try STA 1,S Put updated byte back BEQ EXIT.ERR If zero, no more chances BCC REWRITE If bit 0 was 0, don't home BSR HOME Home and start all over BCC REWRITE If it homed OK, try again EXIT.ERR PULS CC Restore interrupt masks COMA Set carry for error BRA CCDEXIT Finish exit * EXIT.NER PULS CC Restore interrupt masks CLRB Clear carry -- no error CCDEXIT LDA #8 Spindle motor control bit STA >DPORT Deselect disk drive PULS A,X,PC Pull and return * ERR.SECT COMB Set carry flag for error LDB #E$SECT Set error code RTS * READ2 PSHS X,A,CC CC is on top of stack LBSR DSKSTART Start drives and test BCS EXIT.ERR Abort if not ready REREAD LDX 2,S Recover LSN from stack LBSR SEEK Position head at sector BCS RETRY.RD Try again if seek error BSR READ3 Read the sector BCC EXIT.NER Read OK, return data RETRY.RD LDA 1,S Get retry control byte LSRA Indicate another try STA 1,S Put updated byte back BEQ EXIT.ERR If it was all 0, quit BCC REREAD If bit 0 was 0, don't home BSR HOME Home and start all over BCC REREAD If it won't home, quit now BRA EXIT.ERR Exit with an error * WRITE2 LDA #$A2 `Write sector' command BSR RWPREP WTENTRY STA >COMDREG Execute command. This is also an * entry point for the Write Track WAITWDRQ STB >DPORT Wait until WD1793 ready for data * WRTLOOP LDA ,X+ Get byte from data buffer STA >DATAREG Put it in data register STB >DPORT Activate DRQ halt function BRA WRTLOOP Loop until interrupted * VERIFY LDA #$82 `Read sector' command BSR RWPREP STA >COMDREG WAITVDRQ STB >DPORT NOP Give the HALT time to take effect * VFYLOOP LDA >DATAREG Get read data byte STB >DPORT Activate DRQ halt function CMPA ,X+ Compare to source data BEQ VFYLOOP Loop until interrupt if equal * ANDB #$7F Mask off DRQ halt bit STB >DPORT Disable DRQ halt function LBSR KILLCOMD Abort read command ERR.WRT COMB Set carry flag LDB #E$WRITE Set error code RTS * SS.HOME PSHS X,A,CC Set up stack for exit BSR HOME Home drive BRA SS.EXIT Skip to empty-stack exit SS.EXIT4 LEAS 2,S Exit w/4 bytes on stack SS.EXIT2 LEAS 2,S Exit w/2 bytes on stack SS.EXIT BCS EXIT.ERR Exit with error BRA EXIT.NER Exit with no error * HOME LBSR DSKSTART Start and select drive BCS RETURN2 Return if error LDX DRV.ACT,U Point to active drive's table CLR V.TRAK,X Set track number to zero LDD #$43C Home, verify, allow 3 seconds LBSR STEPEX Execute stepping command RETURN2 RTS * SETSTA LDX PD.RGS,Y Point to caller's stack LDB R$B,X Get stacked B register CMPB #SS.RESET `Home' call BEQ SS.HOME Execute Home sequence CMPB #SS.WTRK `Write track' call, used by BEQ WRT.TRAK the Format utility COMB If not one of those, it's an LDB #E$UNKSVC illegal setsta call RTS * READ3 LDA #$82 Read sector command BSR RWPREP STA >COMDREG WAITRDRQ STB >DPORT Wait for DRQ before proceeding NOP Give the Halt a chance to take effect * READLOOP LDA >DATAREG Get data from controller STA ,X+ Store in sector buffer STB >DPORT Activate DRQ halt function BRA READLOOP Loop until interrupted * RWPREP LDX PD.BUF,Y LDB DPRT.IMG,U BITB #$40 BEQ RWPREP1 ORA #8 RWPREP1 LDB #$A8 Set up DRQ halt function ORB DPRT.IMG,U OR in the select bits RTS * * Write an entire track -- used by Format * WRT.TRAK PSHS X,A,CC Set up stack for exit LDA R$U+1,X Get track number LDB R$Y+1,X Get side select bit LDX R$X,X Get track buffer address PSHS X,D Save 'em LBSR DSKSTART Start and select drive BCS SS.EXIT4 Exit if error PULS D Get track number and side LDX DRV.ACT,U Get drive table address BSR SID.PCMP Get drive ready to go TST Q.SEEK,U Different drive/track? BNE WRT.TRK2 If not, no need to seek LDD #$103C Seek, allow 3 seconds LBSR STEPEX Execute stepping command BCS SS.EXIT2 Exit if error WRT.TRK2 PULS X Retrieve track buffer address LDA #$F0 `Write track' command LDB #$A8 Set upt DRQ Halt function ORB DPRT.IMG,U OR in the drive select bits LBSR WTENTRY Just like a Write Sector LBRA SS.EXIT Return to caller * SID.PCMP LSRB Bit 0 of B is set for BCC SIDE.ONE side 2 of disk LDB DPRT.IMG,U Get drive control image byte ORB #$40 Side 2 select bit STB DPRT.IMG,U Activate side 2 select SIDE.ONE CMPA PD.CYL+1,Y If track number exceeds # LBHI ERR.SECT of tracks, return error SD.PCMP2 LDB PD.DNS,Y Check track density of drive LSRB Shift bit 1 (TPI bit) into LSRB carry flag (1 = 96 TPI) LDB #20 Precomp starts at track 21 BCC FORTYTKS on 48 TPI drives, track 41 LSLB on 96 TPI drives FORTYTKS PSHS B Put B where it can be used CMPA ,S+ Does it need precomp? BLS NOPRECMP No, skip next step LDB DPRT.IMG,U Get drive control image byte ORB #$10 Write precompensation bit STB DPRT.IMG,U Activate precompensation NOPRECMP LDB V.TRAK,X Get current track number STB >TRAKREG Update disk controller CMPA V.TRAK,X Same track as last access? BEQ SAMETRAK If so, leave flag set CLR Q.SEEK,U Clear same drive/track flag SAMETRAK STA V.TRAK,X Update track number STA >DATAREG Set destination track LDB DPRT.IMG,U Get disk control byte STB >DPORT Update control port RTS * * Translate logical sector number (LSN) to physical side, track * and sector, activate write precompensation if necessary, * and execute seek command. If any error occurs, return error * number to calling routine. * SEEK LDD PD.SCT,Y Get #sectors per track PSHS X,D Put LSN and sec/trk on stack LDD 2,S Get LSN off stack CLR 2,S Set up track counter FINDTRAK INC 2,S Increment track counter SUBD ,S Subtract sectors in one track BPL FINDTRAK Loop if LSN still positive ADDD ,S++ Restore sector number INCB Sector numbers start at 1 STB 1,S Save sector number PULS A Get track number DECA Compensate for extra count LDX DRV.ACT,U Get active table address LDB DD.FMT,X See if disk is double sided BITB #1 Test #sides bit BEQ SEEK2 If one-sided, skip next step LSRA Divide track number by 2 ROLB Put remainder in B bit 0 SEEK2 BSR SID.PCMP Set up precomp and side sel PULS B Get sector number STB >SECTREG Set destination sector TST Q.SEEK,U Same drive/track? BNE COMDEXIT If so, no need to seek LDD #$143C Seek with verify, allow 3 sec * The next instruction is redundant * BRA STEPEX Execute stepping command * * Execute command in A and wait for it to finish. If it runs * normally or aborts with an error it will exit through NMI; * if it takes an unreasonable amount of time this routine * will abort it and set the carry flag. If the command * involves head movement, use STEPEX to set step rate. * On entry, A contains command code and B contains time limit * in 50-millisecond increments. * STEPEX PSHS A Put raw command on stack LDA PD.STP,Y Get step rate code EORA #3 Convert to 1793's format ORA ,S+ Combine with raw command COMDEX BSR XWAIT50 Go execute command in A and wait 50 ms BCC COMDEXIT Exit if no error CMPB #E$NOTRDY Test for the three valid BEQ KCEXIT error codes for a Type 1 CMPB #E$SEEK disk controller command -- BEQ KCEXIT home, seek or force int- CMPB #E$CRC errupt -- and return the BEQ KCEXIT errors COMDEXIT CLRB No error, clear carry RTS * XWAIT50 STA >COMDREG Execute command in A CLRA Clear carry flag WAIT50MS LDX #$15D8 Almost exactly 50 mSec delay WAITIMER LEAX -1,X Wait specified time for disk BNE WAITIMER controller to issue NMI DECB signaling command completed BNE WAIT50MS or aborted with error KILLCOMD LDA #$D0 Force interrupt, NMI disabled STA >COMDREG Abort command in progress ERR.NRDY LDB #E$NOTRDY Set error code KCEXIT COMA Set carry to flag error RTS * * * Get selected drive ready to read or write. If spindle motors are * stopped, start them and wait until they're up to operating * speed. Check drive number and select drive if number is valid. * Monitor index pulses to ensure door is closed, disk inserted * and turning, etc. Return appropriate error code if any of * these conditions can't be met. * DSKSTART TST >D.DSKTMR Are drives already running? BNE SPINRDY If so, no need to wait CLR DRVS.RDY,U No drives are ready LDD #$80B Motor on, wait 550 mSec STA >DPORT Start spindle motors BSR WAIT50MS Wait for motors to start SPINRDY LDA PD.DRV,Y Get drive number CMPA V.NDRV,U Test for valid drive # BHS ERR.UNIT Return error if not LEAX TABL.ORG,U Compute address of active LDB #DRVMEM drive's parameter table MUL TABL.ORG + (D# * tablesize) LEAX D,X Add computed offset to origin LDA PD.DRV,Y Get drive number again LSLA Set corresponding drv select BNE NOTDRV0 bit -- 1 for D1, 2 for D2 INCA Set bit 0 for drive 0 NOTDRV0 TFR A,B Copy select bit ORB #$28 Enable double density ORCC #INTMASKS Disable IRQ and FIRQ STB >DPORT Enable drive STB DPRT.IMG,U Set image byte CLR Q.SEEK,U Clear same drive/track flag CMPX DRV.ACT,U Is this the same drive? BNE NEWDRIVE If not, leave flag zeroed LDB #$FF Indicate successive accesses STB Q.SEEK,U to the same drive. NEWDRIVE STX DRV.ACT,U Store table address BITA DRVS.RDY,U Has this drive been ready BNE DRVRDY since the motors started? PSHS A Save drive select bit LDD #$D405 Force int, allow 250 mSec BSR COMDEX Look for index pulse PSHS CC Save carry flag condition BSR KILLCOMD Clear index-pulse NMI state PULS CC,A Restore carry flag and A BCS RETURN3 Error if no index pulse DRVRDY ORA DRVS.RDY,U Set corresponding drive STA DRVS.RDY,U ready flag LDA #DISKRUN Restart disk rundown timer STA >D.DSKTMR LDA >STATREG Clear interrupt condition CLRB Return no error RETURN3 RTS * ERR.UNIT COMB Set carry flag LDB E$UNIT Set error code RTS * EMOD CRC bytes SIZE EQU * END