changeset 1570:a4b6825eeb72

ccdisk renamed to rb1773, added CC3 driver into source
author boisy
date Tue, 18 May 2004 01:26:19 +0000
parents ce531f8edad4
children ccf4c764cde9
files level1/modules/makefile level1/modules/rb1773.asm level1/modules/rb1773desc.asm
diffstat 3 files changed, 1591 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/level1/modules/makefile	Tue May 18 01:14:52 2004 +0000
+++ b/level1/modules/makefile	Tue May 18 01:26:19 2004 +0000
@@ -22,7 +22,7 @@
                 clock2_smart clock2_harris clock2_tc3 clock2_soft
 
 RBF		= rbf.mn \
-		ccdisk.dr \
+		rb1773.dr \
 		ddd0_35s.dd d0_35s.dd d1_35s.dd d2_35s.dd d3_35s.dd \
 		ddd0_40d.dd d0_40d.dd d1_40d.dd d2_40d.dd \
 		ddd0_80d.dd d0_80d.dd d1_80d.dd d2_80d.dd
@@ -95,43 +95,43 @@
 DSDD80		= -aCyls=80 -aSides=2 -aSectTrk=18 -aSectTrk0=18 \
 		-aInterlv=3 -aSAS=8 -aDensity=3
 
-ddd0_35s.dd: ccdiskdesc.asm
+ddd0_35s.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(SSDD35) -aDNum=0 -aDD=1
 
-d0_35s.dd: ccdiskdesc.asm
+d0_35s.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(SSDD35) -aDNum=0
 
-d1_35s.dd: ccdiskdesc.asm
+d1_35s.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(SSDD35) -aDNum=1
 
-d2_35s.dd: ccdiskdesc.asm
+d2_35s.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(SSDD35) -aDNum=2
 
-d3_35s.dd: ccdiskdesc.asm
+d3_35s.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(SSDD35) -aDNum=3
 
-ddd0_40d.dd: ccdiskdesc.asm
+ddd0_40d.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(DSDD40) -aDNum=0 -aDD=1
 
-d0_40d.dd: ccdiskdesc.asm
+d0_40d.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(DSDD40) -aDNum=0
 
-d1_40d.dd: ccdiskdesc.asm
+d1_40d.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(DSDD40) -aDNum=1
 
-d2_40d.dd: ccdiskdesc.asm
+d2_40d.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(DSDD40) -aDNum=2
 
-ddd0_80d.dd: ccdiskdesc.asm
+ddd0_80d.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(DSDD80) -aDNum=0 -aDD=1
 
-d0_80d.dd: ccdiskdesc.asm
+d0_80d.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(DSDD80) -aDNum=0
 
-d1_80d.dd: ccdiskdesc.asm
+d1_80d.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(DSDD80) -aDNum=1
 
-d2_80d.dd: ccdiskdesc.asm
+d2_80d.dd: rb1773desc.asm
 	$(AS) $< $(ASOUT)$@ $(AFLAGS) $(DSDD80) -aDNum=2
 
 rel: rel.asm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/level1/modules/rb1773.asm	Tue May 18 01:26:19 2004 +0000
@@ -0,0 +1,1511 @@
+********************************************************************
+* rb1773 - Western Digital 1773 Disk Controller Driver
+*
+* A lot of references to **.CYL or <u00B6 using 16 bit registers can be
+* changed to 8 bit registers with a +1 offset, since track #'s >255 are
+* ignored
+*
+* NOTE: 512 bytes is reserved as a physical sector buffer. Any reads/
+*  writes are done from this buffer to the controller. Copies of the 256
+*  byte chunk needed are done by a block memory move
+
+* $Id$
+*
+* Edt/Rev  YYYY/MM/DD  Modified by
+* Comment
+* ------------------------------------------------------------------
+*  11      1993/05/12  ???
+* Special opts for TC9 to slow controller reads and writes TFM's
+* between sector buffers & in drive table init/copies.
+* Changed software timing loop (drive spin-up) to F$Sleep for 32 ticks
+* Shrunk (slowed slightly) error returns
+* Added blobstop code
+*
+*  11r1    2003/09/03  Boisy G. Pitre
+* Added code to sense if HW is present or not and return error if not.
+
+         nam   rb1773
+         ttl   Western Digital 1773 Disk Controller Driver
+
+         IFP1
+         use   defsfile
+         ENDC
+
+tylg     set   Drivr+Objct   
+atrv     set   ReEnt+rev
+rev      set   $01
+edition  set   11
+
+         IFGT  Level-1
+
+* Configuration Settings
+N.Drives equ   4		number of drives to support
+TC9      equ   0              Set to 1 for TC9 special slowdowns
+PRECOMP  equ   0              Set to 1 to turn on write precompensation
+
+* WD-17X3 Definitions
+WD_Cmd   equ   $08
+WD_Stat  equ   WD_Cmd
+WD_Trak  equ   $09
+WD_Sect  equ   $0A
+WD_Data  equ   $0B
+
+         mod   eom,name,tylg,atrv,start,size
+
+u0000    rmb   DRVBEG+(DRVMEM*N.Drives)
+u00A7    rmb   2              Last drive table accessed (ptr)
+u00A9    rmb   1              Bit mask for control reg (drive #, side,etc)
+u00AA    rmb   1
+sectbuf  rmb   2              Ptr to 512 byte sector buffer
+u00AD    rmb   1
+u00AE    rmb   1
+FBlock   rmb   2              block number for format
+         IFGT  Level-1
+FTask    rmb   1              task number for format
+         ENDC
+u00B1    rmb   2              Vi.Cnt word for VIRQ
+u00B3    rmb   2              Vi.Rst word for VIRQ
+u00B5    rmb   1              Vi.Stat byte for VIRQ (drive motor timeout)
+u00B6    rmb   2              OS9's logical sector #
+u00B8    rmb   1              PCDOS (512 byte sector) sector #
+size     equ   .
+
+         fcb   DIR.+SHARE.+PEXEC.+PWRIT.+PREAD.+EXEC.+UPDAT.
+
+name     equ   *
+         IFEQ  Level-1
+         fcs   /CCDisk/
+         ELSE
+         fcs   /rb1773/
+         ENDC
+         fcb   edition
+
+VIRQCnt  fdb   $00F0          Initial count for VIRQ (240)
+
+IRQPkt   fcb   $00            Normal bits (flip byte)
+         fcb   $01            Bit 1 is interrupt request flag (Mask byte)
+         fcb   10             Priority byte
+
+* Init
+*
+* Entry:
+*    Y  = address of device descriptor
+*    U  = address of device memory area
+*
+* Exit:
+*    CC = carry set on error
+*    B  = error code
+*     
+* New code added 09/03/2003 by Boisy G. Pitre
+* Write a pattern to $FF4B and read it back to verify that the hardware
+* does exist.
+Init     ldx   V.PORT,u       get Base port address
+         lda   WD_Data,x      get byte at FDC Data register
+         coma                 complement it to modify it
+         sta   WD_Data,x      write it
+         clrb
+Init2    decb                 delay a bit...
+         bmi   Init2
+         suba  WD_Data,x      read it back
+         lbne  NoHW           if not zero, we didn't read what we wrote
+**
+         IFEQ  Level-1
+         clr   >D.DskTmr      flag drive motor as not running
+         ELSE
+         clr   <D.MotOn       flag drive motor as not running
+         ENDC
+         leax  WD_Stat,x      point to Status/Command register
+         lda   #$D0           force Interrupt command
+         sta   ,x             send to FDC
+         lbsr  L0406          time delay for ~ 108 cycles
+         lda   ,x             eat status register
+         ldd   #$FF*256+N.Drives  'invalid' value & # of drives
+         sta   >u00B8,u       set 512 byte sector # to bogus value
+         sta   >u00B8+1,u
+         leax  DRVBEG,u       point to start of drive tables
+L004B    sta   ,x             DD.TOT MSB to bogus value
+         sta   <V.TRAK,x      init current track # to bogus value
+         leax  <DRVMEM,x      point to next drive table
+         decb                 done all 4 drives yet?
+         bne   L004B          no, init them all
+         leax  >NMISvc,pc     point to NMI service routine
+         IFGT  Level-1
+         stx   <D.NMI         install as system NMI
+         ELSE
+         stx   >D.XNMI+1	NMI jump vector operand
+         lda   #$7E		JMP code
+         sta   >D.XNMI		NMI jump vector opcode
+         ENDC
+         pshs  y              save device dsc. ptr
+         leay  >u00B5,u       point to Vi.Stat in VIRQ packet
+         tfr   y,d            make it the status register ptr for IRQ
+         leay  >IRQSvc,pc     point to IRQ service routine
+         leax  >IRQPkt,pc     point to IRQ packet
+         os9   F$IRQ          install IRQ
+         puls  y              Get back device dsc. ptr
+         bcs   Return         If we can't install IRQ, exit
+         ldd   #512           Request 512 byte sector buffer
+         pshs  u              Preserve device mem ptr
+         os9   F$SRqMem       Request sector buffer
+         tfr   u,x            Move ptr to sector buffer to x
+         puls  u              Restore device mem ptr
+         bcs   Return         If error, exit with it
+         stx   >sectbuf,u     Save ptr to sector buffer
+
+* GetStat
+*
+* Entry:
+*    A  = function code
+*    Y  = address of path descriptor
+*    U  = address of device memory area
+*
+* Exit:
+*    CC = carry set on error
+*    B  = error code
+*
+GetStat  clrb                 no GetStt calls - return, no error, ignore
+Return   rts   
+
+* Term
+*
+* Entry:
+*    U  = address of device memory area
+*
+* Exit:
+*    CC = carry set on error
+*    B  = error code
+*
+Term     leay  >u00B1,u       Point to VIRQ packet
+         IFNE  H6309
+         tfr   0,x            "remove"
+         ELSE
+         ldx   #$0000
+         ENDC
+         os9   F$VIRQ         Remove VIRQ
+         IFNE  H6309
+         tfr   0,x            "remove"
+         ELSE
+         ldx   #$0000
+         ENDC
+         os9   F$IRQ          Remove IRQ
+         pshs  u              Save device mem ptr
+         ldu   >sectbuf,u     Get pointer to sector buffer
+         ldd   #512           Return sector buffer memory
+         os9   F$SRtMem 
+         puls  u              Restore device mem ptr
+         clr   >DPort         shut off drive motors
+         IFEQ  Level-1
+         clr   >D.DskTmr      Clear out drive motor timeout flag
+         ELSE
+         clr   <D.MotOn       Clear out drive motor timeout flag
+         ENDC
+L00AB    rts                  return
+
+* Check if 512 byte sector conversion needed
+* Entry: B:X=LSN
+*          U=Static mem ptr
+*          Y=Path dsc. ptr
+* Exit:    X=New LSN (same as original for 256 byte sectors, 1/2 of original
+*            for 512 byte sectors
+L00AC    pshs  x,b            Save LSN
+         stx   >u00B6,u       Save OS9 LSN
+         lda   <PD.TYP,y      Get device type from path dsc.
+         anda  #%00000100     Mask out all but 512 byte sector flag
+         bne   L00BB          512 byte sectors, go process
+L00CA    puls  pc,x,b         Restore LSN & return
+
+* 512 byte sector processing goes here
+L00BB    puls  x,b            Get back LSN
+         clrb                 Clear carry for rotate (also high byte of LSN)
+         tfr   x,d            Move to mathable register
+         IFNE  H6309
+         rord                 Divide LSN by 2
+         ELSE
+         rora
+         rorb
+         ENDC
+         tfr   d,x            Move new LSN back to X
+         stx   >u00B8,u       Save 'physical' LSN (for controller)
+         clrb                 No error & return
+         rts   
+
+start    lbra  Init
+         bra   Read
+         nop
+         lbra  Write
+         bra   GetStat
+         nop
+         lbra  SetStat
+         bra   Term
+         nop
+
+* Read
+*
+* Entry:
+*    B  = MSB of LSN
+*    X  = LSB of LSN
+*    Y  = address of path descriptor
+*    U  = address of device memory area
+*
+* Exit:
+*    CC = carry set on error
+*    B  = error code
+*
+Read     bsr   L00AC          Go check for 512 byte sector/adjust if needed
+         lda   #%10010001     Error flags (see Disto SCII source)
+         pshs  x              Preserve sector #
+         lbsr  L0162          Go read the sector
+         puls  x              Restore sector #
+         bcs   L00AB          If error, exit
+         pshs  y,x            Save path dsc ptr & LSN
+         leax  ,x             LSN0?
+         bne   L012D          No, go calculate normally
+         puls  y,x            Yes, restore path dsc ptr & LSN
+         lda   <PD.TYP,y      Get type from path dsc.
+         bita  #TYP.NSF       Standard OS-9 format?
+         beq   L00F0          Yes, skip ahead
+         lbsr  L051A
+         pshs  y,x            save path dsc ptr
+         bra   L012D
+
+* LSN0, standard OS-9 format
+L00F0    ldx   >sectbuf,u     Get ptr to sector buffer
+         pshs  y,x            Preserve path dsc. ptr & sector buffer ptr
+         ldy   >u00A7,u       Get last drive table accessed ptr
+         IFNE  H6309
+         ldw   #DD.SIZ        # bytes to copy from new LSN0 to drive table
+         tfm   x+,y+          Copy them
+         ELSE
+         ldb   #DD.SIZ
+L00F0Lp  lda   ,x+
+         sta   ,y+
+         decb
+         bne   L00F0Lp
+         ENDC
+         ldy   >u00A7,u       Get drive table ptr back
+         lda   <DD.FMT,y      Get format for disk in drive
+         ldy   2,s            restore path descriptor pointer
+         ldb   <PD.DNS,y      Get path's density settings
+         bita  #FMT.DNS       Disk in drive double density?
+         beq   L0115          No, all drives can read single, skip ahead
+         bitb  #DNS.MFM       Can our path dsc. handle double density?
+         beq   erbtyp         No, illegal
+L0115    bita  #FMT.TDNS      Is new disk 96 tpi?
+         beq   L011D          No, all drives handle 48 tpi, so skip ahead
+         bitb  #DNS.DTD       Can path dsc. handle 96 tpi?
+         beq   erbtyp         No, illegal
+L011D    bita  #FMT.SIDE      Is new disk double sided?
+         beq   L0128          No, all drives handle single sided, we're done
+         lda   <PD.SID,y      Get # sides path dsc. can handle
+         suba  #2             sides higher or equal to 2?
+         blo   erbtyp         Yes, exit with illegal type error
+L0128    clrb                 No error
+*        puls  y,x            ??? 2 USELESS LINES?
+*        pshs  y,x
+* LSN's other than 0 come straight here
+L012D    ldy   2,s            Get path dsc. ptr back??
+         ldx   PD.BUF,y       Get path dsc. buffer ptr
+         lda   <PD.TYP,y      Get path dsc. disk type
+         ldy   >sectbuf,u     Get ptr to sector buffer
+         IFNE  H6309
+         ldw   #256           OS9 sector size (even if physical was 512)
+         ENDC
+         anda  #%00000100     Mask out all but 512 byte sector flag
+         beq   L014B          If normal sector, just copy it
+         ldd   >u00B6,u       Get OS9's LSN (twice of the 'real' 512 sector)
+         andb  #$01           Mask out all but odd/even sector indicator
+         beq   L014B          Even, use 1st half of 512 byte sector
+         IFNE  H6309
+         addr  w,y            Odd, bump sector buffer ptr to 2nd half
+         ELSE
+         leay  256,y
+         ENDC
+L014B    equ   *
+         IFNE  H6309
+         tfm   y+,x+          Copy from physical sector buffer to PD buffer
+         puls  pc,y,x         restore path dsc & sector buffer ptrs & return
+         ELSE
+         pshs  d
+         clrb
+L014BLp  lda   ,y+
+         sta   ,x+
+         decb
+         bne   L014BLp
+         puls  pc,y,x,d       restore path dsc & sector buffer ptrs & return
+         ENDC
+
+erbtyp   comb  
+         ldb   #E$BTyp        Error - wrong type error
+         puls  pc,y,x
+
+* Read error - retry handler
+L0159    bcc   L0162          Normal retry, try reading again
+         pshs  x,d            Preserve regs
+         lbsr  sktrk0         Seek to track 0 (attempt to recalibrate)
+         puls  x,d            Restore regs & try reading again
+
+L0162    pshs  x,d            Preserve regs
+         bsr   L016F          Go read sector
+         puls  x,d            Restore regs (A=retry flags)
+         bcc   L01D7          No error, return
+         lsra                 Shift retry flags
+         bne   L0159          Still more retries allowed, go do them
+* otherwise, final try before we give up
+L016F    lbsr  L02AC          Do double-step/precomp etc. if needed, seek
+         bcs   L01D7          Error somewhere, exit with it
+L0176    ldx   >sectbuf,u     Get physical sector buffer ptr
+*         pshs  y,cc           Preserve timeout timer & CC
+         ldb   #$80           Read sector command
+         bsr   L01A1          Send to controller & time delay to let it settle
+*** Next few lines are commented out for blobstop patches
+*L0180    bita  >DPort+WD_Stat check status register
+*         bne   L0197          eat it & start reading sector
+*         leay  -1,y           bump timeout timer down
+*         bne   L0180          keep trying until it reaches 0 or sector read
+*         lda   >u00A9,u       get current drive settings
+*         ora   #%00001000     turn drive motor on
+*         sta   >DPort         send to controller
+*         puls  y,cc           restore regs
+*         lbra  L03E0          exit with Read Error
+*** Blobstop fixes
+         stb   >DPort         send command to FDC
+         nop                  allow HALT to take effect
+         nop
+         bra   L0197          and a bit more time
+* Read loop - exited with NMI
+* Entry: X=ptr to sector buffer
+*        B=Control register settings
+L0197    lda   >DPort+WD_Data get byte from controller
+         sta   ,x+            store into sector buffer
+*         stb   >DPort        drive info
+         nop               -- blobstop fix
+         bra   L0197          Keep reading until sector done
+
+L01A1    orcc  #IntMasks      Shut off IRQ & FIRQ
+         stb   >DPort+WD_Cmd  Send command
+*         ldy   #$FFFF
+         ldb   #%00101000     Double density & motor on
+         orb   >u00A9,u       Merge with current drive settings
+         stb   >DPort         Send to control register
+         ldb   #%10101000     Enable halt, double density & motor on
+         orb   >u00A9,u       Merge that with current drive settings
+         lbra  L0406          Time delay to wait for command to settle
+*         lda   #$02
+*L01BE    rts   
+
+* Write
+*
+* Entry:
+*    B  = MSB of LSN
+*    X  = LSB of LSN
+*    Y  = address of path descriptor
+*    U  = address of device memory area
+*
+* Exit:
+*    CC = carry set on error
+*    B  = error code
+*
+Write    lbsr  L00AC          Go adjust LSN for 512 byte sector if needed
+         lda   #%1001001      Retry flags for I/O errors (see Disto SCII source)
+L01C4    pshs  x,d            Preserve LSN, retries
+         bsr   L01E8          Go write the sector
+         puls  x,d            Restore LSN, retries
+         bcs   L01D8          Error writing, go to write retry handler
+         tst   <PD.VFY,y      No error, do we want physical verify?
+         bne   L01D6          No, exit without error
+         lbsr  verify         Go re-read & verify 32 out of 256 bytes
+         bcs   L01D8          Error on verify, go to write retry handler
+L01D6    clrb                 No error & return
+L01D7    rts   
+
+* Write error retry handler
+L01D8    lsra                 Shift retry flags
+         lbeq  L03AF          Too many retries, exit with error
+         bcc   L01C4          Normal retry, attemp to re-write sector
+         pshs  x,d            Preserve flags & sector #
+         lbsr  sktrk0         Seek to track 0 (attempt to recalibrate)
+         puls  x,d            Restore flags & sector #
+         bra   L01C4          Try re-writing now
+
+* 512 byte sector write here
+L01E8    lbsr  L02AC          Go do double-step/write precomp if needed
+         bcs   L01D7          Error, exit with it
+         pshs  y,d            Preserve path dsc. ptr & LSN
+         lda   <PD.TYP,y      Get device type
+         anda  #%00000100     512 byte sector?
+         beq   L020D          No, skip ahead
+         lda   #$91           ??? appears to be useless
+         lbsr  L0176          Go read the sector in
+         ldd   >u00B6,u       Get OS9 LSN
+         andb  #$01           Even or odd?
+         beq   L020D          Even, skip ahead
+         ldx   >sectbuf,u     Get physical sector buffer ptr
+         leax  >$0100,x       Point to 2nd half
+         bra   L0211          Copy caller's buffer to 2nd half of sector
+
+L020D    ldx   >sectbuf,u     Get physical sector buffer ptr
+
+L0211    ldy   PD.BUF,y       Get path dsc. buffer ptr
+         IFNE  H6309
+         ldw   #256           Copy write buffer to sector buffer
+         tfm   y+,x+
+         ELSE
+         clrb
+L0211Lp  lda   ,y+
+         sta   ,x+
+         decb
+         bne   L0211Lp
+         ENDC
+         puls  y,d             Get path dsc. ptr & LSN back
+         ldx   >sectbuf,u      Get physical sector buffer ptr again
+         ldb   #$A0            Write sector command
+
+* Format track comes here with B=$F0 (write track)
+*L0224    pshs  y,cc           Preserve path dsc. ptr & CC
+L0224     lbsr  L01A1          Send command to controller (including delay)
+*** Commented out for blobstop fixes
+*L0229    bita  >DPort+WD_Stat Controller done yet?
+*         bne   L0240          Yes, go write sector out
+*         leay  -$01,y         No, bump wait counter
+*         bne   L0229          Still more tries, continue
+*         lda   >u00A9,u       Get current drive control register settings
+*         ora   #%00001000     Drive motor on (but drive select off)
+*         sta   >DPort         Send to controller
+*         puls  y,cc           Restore regs
+*         lbra  L03AF          Check for errors from status register
+
+         IFGT  Level-1
+*** added blobstop
+         lda   FBlock+1,u      get the block number for format
+         beq   L0230           if not format, don't do anything
+         sta   >$FFA1          otherwise map the block in
+         ENDC
+
+L0230    stb   >DPort          send command to FDC
+         bra   L0240           wait a bit for HALT to enable
+* Write sector routine (Entry: B= drive/side select) (NMI will break out)
+L0240    nop               --- wait a bit more
+         lda   ,x+             Get byte from write buffer
+         sta   >DPort+WD_Data  Save to FDC's data register
+* EAT 2 CYCLES: TC9 ONLY (TRY 1 CYCLE AND SEE HOW IT WORKS)
+         IFEQ TC9-1
+         nop
+         nop
+         ENDC
+*         stb   >DPort        Set up to read next byte
+         bra   L0240          Go read it
+
+* NMI routine
+NMISvc   leas  R$Size,s       Eat register stack
+*         puls  y,cc           Get path dsc. ptr & CC
+         IFGT  Level-1
+         ldx   <D.SysDAT  get pointer to system DAT image
+         lda   3,x        get block number 1
+         sta   >$FFA1     map it back into memory
+         andcc #^IntMasks turn IRQ's on again
+         ELSE
+*         puls  y,cc           Get path dsc. ptr & CC
+         ENDC
+         ldb   >DPort+WD_Stat  Get status register
+         bitb  #%00000100     Did we lose data in the transfer?
+*         lbne  L03E0          Yes, exit with Read Error
+         lbeq  L03B2          Otherwise, check for drive errors
+         comb             -- blobstop error code
+         ldb   #E$DevBsy  -- device busy
+         rts              -- and exit
+
+verify   pshs  x,d
+         ldx   PD.BUF,y       Get write buffer ptr
+         pshs  x              Preserve it
+         ldx   >sectbuf,u     Get sector buffer ptr
+         stx   PD.BUF,y       Save as write buffer ptr
+         ldx   4,s
+         lbsr  L016F          Go read sector we just wrote
+         puls  x              Get original write buffer ptr
+         stx   PD.BUF,y       Restore path dsc. version
+         bcs   L02A3          If error reading, exit with it
+         pshs  u,y            Preserve device mem, path dsc. ptrs
+         ldb   <PD.TYP,y      Get type from path dsc.
+         ldy   >sectbuf,u     Get sector buffer ptr
+         andb  #%00000100     512 byte sector?
+         beq   L028D          No, skip ahead
+         ldd   >u00B6,u       Get OS9's sector #
+         andb  #$01           Odd/even sector?
+         beq   L028D          Even; compare first half
+         leay  >$0100,y       Odd, compare second half
+L028D    tfr   x,u            Move PD.BUF ptr to U (since cmpx is faster)
+         lda   #32            # of 'spotty' checks to do
+L028F    ldx   ,u             Get 2 bytes from original write buffer
+         cmpx  ,y             Same as corresponding bytes in re-read sector?
+         bne   L029F          No, error & return
+         leau  8,u            Skip next 6 bytes
+         leay  8,y
+         deca                 Done our 'spotty' check?
+         bne   L028F          No, continue
+         fcb   $8C            skip the next 2 bytes
+
+L029F    orcc  #Carry
+L02A1    puls  u,y
+L02A3    puls  pc,x,d
+
+L02A5    pshs  a              Save Caller's track #
+         ldb   <V.TRAK,x      Get track # drive is currently on
+         bra   L02E9          Go save it to controller & continue
+
+L02AC    lbsr  L0376          Go set up controller for drive, spin motor up
+         bsr   L032B          Get track/sector # (A=Trk, B=Sector)
+         pshs  a              Save track #
+         lda   >u00AD,u       Get side 1/2 flag
+         beq   L02C4          Side 1, skip ahead
+         lda   >u00A9,u       Get control register settings
+         ora   #%01000000     Set side 2 (drive 3) select
+         sta   >u00A9,u       Save it back
+L02C4    lda   <PD.TYP,y      Get drive type settings
+         bita  #%00000010     ??? (Base 0/1 for sector #?)
+         bne   L02CC          Skip ahead
+         incb                 Bump sector # up by 1
+L02CC    stb   >DPort+WD_Sect Save into Sector register
+         ldx   >u00A7,u       Get last drive table accessed
+         ldb   <V.TRAK,x      Get current track # on device
+         lda   <DD.FMT,x      Get drive format specs
+         lsra                 Shift track & bit densities to match PD
+         eora  <PD.DNS,y      Check for differences with path densities
+         anda  #%00000010     Keep only 48/96 tpi differences
+         pshs  a              Save differences
+         lda   1,s            Get track # back
+         tst   ,s+            Are tpi's different?
+         beq   L02E9          No, continue normally
+         lsla                 Yes, multiply track # by 2 ('double-step')
+         lslb                 Multiply current track # by 2 ('double-step')
+L02E9    stb   >DPort+WD_Trak Save current track # onto controller
+
+* From here to the line before L0307 is for write precomp, but is not used.
+* Unless write precomp is needed, all of this is useless
+* I think most (if not all) drives do NOT need precomp
+         IFEQ  PRECOMP-1
+         ldb   #21            Pre-comp track #
+         pshs  b              Save it
+         ldb   <PD.DNS,y      Get current density settings
+         andb  #%00000010     Just want to check track density
+         beq   L02F9          48 tpi, skip ahead
+         lsl   ,s             Multiply pre-comp value by 2 ('double-step')
+L02F9    cmpa  ,s+            Is track # high enough to warrant precomp?
+         bls   L0307          No, continue normally
+         ldb   >u00A9,u
+         orb   #%00010000     Turn on Write precomp
+         stb   >u00A9,u
+         ENDC
+
+L0307    ldb   >u00AA,u       ??? Get flag (same drive flag?)
+         bne   L0314          no, skip ahead
+         ldb   ,s             get track #
+         cmpb  <V.TRAK,x      same as current track on this drive?
+         beq   L0321          yes, skip ahead
+L0314    sta   >DPort+WD_Data save track # to data register
+         ldb   <PD.STP,y      get stepping rate
+         andb  #%00000011     just keep usable settings (6-30 ms)
+         eorb  #%00011011     set proper bits for controller
+         lbsr  L03E4          send command to controller & time delay
+L0321    puls  a              get track # back
+         sta   <V.TRAK,x      save as current track #
+         sta   >DPort+WD_Trak save to controller
+         clrb                 no error & return
+         rts   
+
+* Entry: B:X LSN
+* Exit:  A=Track #
+*        B=Sector #
+*   <u00AD=00 = Head 1 , $FF = Head 2
+L032B    tstb                 Sector # > 65535?
+         bne   L033F          Yes, illegal for floppy
+         tfr   x,d            Move sector # to D
+         leax  ,x         LSN 0?
+         beq   L0371          Yes, exit this routine
+         ldx   >u00A7,u       Get previous drive table ptr
+         cmpd  DD.TOT+1,x     Within range of drive spec?
+         blo   L0343          Yes, go calculate track/sector #'s
+L033F    comb                 Exit with Bad sector # error
+         ldb   #E$Sect
+         rts   
+
+* Calculate track/sector #'s?
+L0343    stb   >u00AE,u       Save LSB of LSN
+         clr   ,-s            Clear track # on stack
+         ldb   <DD.FMT,x      Get drive format
+         lsrb                 Shift out # sides into carry
+         ldb   >u00AE,u       Get LSB of LSN again
+         bcc   L0367          Single sided drive, skip ahead
+         bra   L035D          Double sided drive, skip ahead
+* Double sided drive handling here
+L0355    com   >u00AD,u       ???? Odd/even sector track flag?
+         bne   L035D          Odd, so don't bump track # up
+         inc   ,s             Bump up track #
+
+L035D    subb  DD.TKS,x       Subtract # sectors/track
+         sbca  #$00
+         bcc   L0355          Still more sectors left, continue
+         bra   L036D          Wrapped, skip ahead
+* Single sided drive handling here
+L0365    inc   ,s             Bump track # up
+
+L0367    subb  DD.TKS,x       Subtract # sectors/track
+         sbca  #$00
+         bcc   L0365          Still more, go bump the track up
+L036D    addb  $03,x          Bump sector # back up from negative value
+         puls  a              Get the track #
+L0371    rts                  A=track #, B=Sector #, <u00AD=Odd
+
+* Drive control register bit mask table
+L0372    fcb   $01            Drive 0
+         fcb   $02            Drive 1
+         fcb   $04            Drive 2
+         fcb   $40            Drive 3 / Side select
+
+L0376    clr   >u00AA,u       ???
+
+chkdrv   lda   <PD.DRV,y      Get drive # requested
+         cmpa  #4             Drive 0-3?
+         blo   L0385          Yes, continue normally
+NoHW     comb                 Illegal drive # error
+         ldb   #E$Unit
+         rts   
+
+* Entry: A=drive #, X=LSN (Physical, not OS9 logical if PCDOS disk)
+L0385    pshs  x,d            Save sector #, drive # & B???
+         leax  >L0372,pc      Point to drive bit mask table
+         ldb   a,x            Get bit mask for drive # we want
+         stb   >u00A9,u       Save mask
+         leax  DRVBEG,u       Point to beginning of drive tables
+         ldb   #DRVMEM        Get size of each drive table
+         mul                  Calculate offset to drive table we want
+         leax  d,x            Point to it
+         cmpx  >u00A7,u       Same as Last drive table accessed?
+         beq   L03A6          Yes, skip ahead
+         stx   >u00A7,u       Save new drive table ptr
+         com   >u00AA,u       ??? Set flag
+L03A6    clr   >u00AD,u       Set side (head) flag to side 1
+         lbsr  L04B3          Go set up VIRQ to wait for drive motor
+         puls  pc,x,d         Restore sector #,drive #,B & return
+
+L03AF    ldb   >DPort+WD_Stat Get status register from FDC
+L03B2    bitb  #%11111000     Any of the error bits set?
+         beq   L03CA          No, exit without error
+         aslb             Drive not ready?
+         bcs   L03CC          Yes, use that error code
+         aslb             Write protect error?
+         bcs   L03D0          Yes, use that error code
+         aslb             Write fault error?
+         bcs   L03D4          Yes, use that error code
+         aslb             Sector not found?
+         bcs   L03D8          Yes, use Seek error code
+         aslb             CRC error?
+         bcs   L03DC          Yes, use that error code
+L03CA    clrb                 No error & return
+         rts   
+
+L03CC    ldb   #E$NotRdy      not ready
+         fcb   $8C        skip 2 bytes
+
+L03D0    ldb   #E$WP          write protect
+         fcb   $8C        skip 2 bytes
+
+L03D4    ldb   #E$Write       write error
+         fcb   $8C
+
+L03D8    ldb   #E$Seek        seek error
+         fcb   $8C
+
+L03DC    ldb   #E$CRC         CRC error
+*         fcb   $8C
+
+*L03E0    ldb   #E$Read        Read error
+         orcc  #Carry         set carry
+         rts   
+
+L03E4    bsr   L0404          Send command to controller & waste some time
+L03E6    ldb   >DPort+WD_Stat Check FDC status register
+         bitb  #$01           Is controller still busy?
+         beq   L0403          No, exit
+         ldd   >VIRQCnt,pc    Get initial count value for drive motor speed
+         std   >u00B1,u       Save it
+         bra   L03E6          Wait for controller to finish previous command
+
+* Send command to FDC
+L03F7    lda   #%00001000     Mask in Drive motor on bit
+         ora   >u00A9,u       Merge in drive/side selects
+         sta   >DPort         Turn the drive motor on & select drive
+         stb   >DPort+WD_Cmd  Save command & return
+L0403    rts   
+
+L0404    bsr   L03F7          Go send command to controller
+
+* This loop has been changed from nested LBSRs to timing loop.
+* People with crystal upgrades should modify the loop counter
+* to get a 58+ us delay time.  MINIMUM 58us.
+L0406    pshs  a          14 cycles, plus 3*loop counter
+         lda   #29        (only do about a 100 cycle delay for now)
+L0409    deca             for total ~63 us delay (123 cycles max.)
+         bne   L0409
+         puls  a,pc       restore register and exit
+
+* SetStat
+*
+* Entry:
+*    A  = function code
+*    Y  = address of path descriptor
+*    U  = address of device memory area
+*
+* Exit:
+*    CC = carry set on error
+*    B  = error code
+*
+SetStat  ldx   PD.RGS,y       Get caller's register stack ptr
+         ldb   R$B,x          Get function code
+         cmpb  #SS.WTrk       Write track?
+         beq   SSWTrk         Yes, go do it
+         cmpb  #SS.Reset      Restore head to track 0?
+         lbeq  sktrk0         Yes, go do it --- beq
+         comb                 set carry for error
+         ldb   #E$UnkSvc      return illegal service request error
+         rts   
+
+SSWTrk   pshs  u,y            preserve register stack & descriptor
+
+         IFEQ   Level-1
+
+         ldd   #$1A00         Size of buffer to hold entire track image
+         os9   F$SRqMem       Request memory from system
+         bcs   L0489          Error requesting, exit with it
+         stu   >FBlock,x
+
+         ELSE
+
+*--- new code
+         ldb   #1         1 block to allocate
+         os9   F$AllRAM   allocate some RAM
+         bcs   L0489      error out if at all
+         leax  >FBlock,u   point to 'my' DAT image
+         std   ,x         save a copy of the block
+         os9   F$ResTsk   reserve a task number for the copy
+         bcs   FError     error out
+         stb   2,x        save temporary task number in FTask,u
+         lslb             2 bytes per entry
+         ldu   <D.TskIPt  get task image table pointer
+         stx   b,u        save pointer to the task's DAT image
+         lsrb             get the right number again
+         IFNE  H6309
+         tfr   0,u        destination is address 0
+         ELSE
+         ldu   #$0000
+         ENDC
+*--- end new code
+
+         ldx   2,s            get pointer to descriptor
+*         stu   >FBlock,x
+         ldx   <D.Proc        Get current process ptr
+         lda   P$Task,x       Get task # for current process
+*         ldb   <D.SysTsk      Get system task #
+         ldy   ,s
+         ldx   PD.RGS,y       Get register stack ptr
+         ldx   R$X,x          Get ptr to caller's track buffer
+         ldy   #$1A00         Size of track buffer
+         os9   F$Move         Copy from caller to temporary task
+         bcs   L0479          Error copying, exit
+
+         ENDC
+
+         puls  u,y
+         pshs  u,y
+         lbsr  L0376          Go check drive #/wait for it to spin up
+         ldx   PD.RGS,y       Get caller's register stack ptr
+         ldb   R$Y+1,x        Get caller's side/density
+         bitb  #$01           Check side
+         beq   L0465          Side 1, skip ahead
+         com   >u00AD,u
+         ldb   >u00A9,u       Get current control register settings
+         orb   #%01000000     Mask in side 2
+         stb   >u00A9,u       Save updated control register
+L0465    lda   R$U+1,x        Get caller's track #
+         ldx   >u00A7,u       Get current drive table ptr
+         lbsr  L02A5          
+         bcs   L0489
+         ldb   #$F0           Write track command?
+*---
+         IFEQ  Level-1
+         ldx   >FBlock,u
+         ELSE
+         ldx   #$2000     start writing from block 1
+         ENDC
+
+         lbsr  L0224          Go write the track
+L0479    ldu   2,s
+         pshs  b,cc           Preserve error
+
+         IFEQ  Level-1
+
+         ldu   >FBlock,u       Get ptr to track buffer
+         ldd   #$1A00         Return track buffer
+         os9   F$SRtMem 
+
+         ELSE
+
+         ldb   >FTask,u   point to task
+         os9   F$RelTsk   release the task
+         fcb   $8C        skip 2 bytes
+
+         ENDC
+
+* format comes here when block allocation passes, but task allocation
+* gives error.  So er de-allocate the block.
+FError   
+         IFGT  Level-1
+         pshs  b,cc       save error code, cc
+         ldx   >FBlock,u   point to block
+         ldb   #1         1 block to return
+         os9   F$DelRAM   de-allocate image RAM blocks
+         clr   FBlock+1,u ensure that the block # in FBlock is zero.
+         puls  b,cc           Restore error
+         ENDC
+
+L0489    puls  pc,u,y         Restore regs & return
+
+* seek the head to track 0
+sktrk0   lbsr  chkdrv
+         ldx   >u00A7,u
+         clr   <$15,x
+         lda   #$05
+L0497    ldb   <PD.STP,y
+         andb  #%00000011     Just keep usable settings (6-30 ms)
+         eorb  #%01001011     Set proper bits for controller
+         pshs  a
+         lbsr  L03E4
+         puls  a
+         deca  
+         bne   L0497
+         ldb   <PD.STP,y
+         andb  #%00000011     Just keep usable settings (6-30 ms)
+         eorb  #%00001011     Set proper bits for controller
+         lbra  L03E4
+
+L04B3    pshs  y,x,d          Preserve regs
+         ldd   >VIRQCnt,pc    Get VIRQ initial count value
+         std   >u00B1,u       Save it
+         lda   >u00A9,u       ?Get drive?
+         ora   #%00001000     Turn drive motor on for that drive
+         sta   >DPort         Send drive motor on command to FDC
+         IFEQ  Level-1
+         lda   >D.DskTmr      Get VIRQ flag
+         ELSE
+         lda   <D.MotOn       Get VIRQ flag
+         ENDC
+         bmi   L04DE          Not installed yet, try installing it
+         bne   L04E0          Drive already up to speed, exit without error
+
+* Drive motor speed timing loop (could be F$Sleep call now) (was over .5 sec)
+         ldx   #32            wait for 32 ticks
+         os9   F$Sleep
+
+L04DE    bsr   InsVIRQ        Install VIRQ to wait for drive motors
+L04E0    clrb                 No error & return
+         puls  pc,y,x,d
+
+InsVIRQ  lda   #$01           Flag drive motor is up to speed
+         IFEQ  Level-1
+         sta   >D.DskTmr
+         ELSE
+         sta   <D.MotOn
+         ENDC
+         ldx   #$0001         Install VIRQ entry
+         leay  >u00B1,u       Point to packet
+         clr   Vi.Stat,y      Reset Status byte
+         ldd   >VIRQCnt,pc    Get initial VIRQ count value
+         os9   F$VIRQ         Install VIRQ
+         bcc   VIRQOut        No error, exit
+         lda   #$80           Flag that VIRQ wasn't installed
+         IFEQ  Level-1
+         sta   >D.DskTmr
+         ELSE
+         sta   <D.MotOn
+         ENDC
+VIRQOut  clra  
+         rts   
+
+* IRQ service routine for VIRQ (drive motor time)
+* Entry: U=Ptr to VIRQ memory area
+IRQSvc   pshs  a
+         lda   <D.DMAReq
+         beq   L0509
+         bsr   InsVIRQ
+         bra   IRQOut
+L0509    sta   >DPort
+         IFNE  H6309
+         aim   #$FE,>u00B5,u
+         ELSE
+         lda   u00B5,u
+         anda  #$FE
+         sta   u00B5,u
+         ENDC
+*         fdb   u00B5      --- so changes in data size won't affect anything
+         IFEQ  Level-1
+         clr   >D.DskTmr
+         ELSE
+         clr   <D.MotOn
+         ENDC
+IRQOut   puls  pc,a
+
+* Non-OS9 format goes here
+* Entry: X=LSN
+*        Y=Path dsc. ptr
+*        U=Device mem ptr
+L051A    pshs  x              Preserve Logical sector #
+         ldx   >u00A7,u       Get last drive table accessed ptr
+         clra
+         pshs  x,a            Save ptr & NUL byte
+         IFNE  H6309
+         ldw   #$14           Clear 20 bytes
+         tfm   s,x+
+         ELSE
+         ldb   #$14
+L051ALp  clr   ,x+
+         decb
+         bne   L051ALp
+         ENDC
+         puls  x,a            Eat NUL & get back drive table ptr
+         ldb   <PD.CYL+1,y    Get # cylinders on drive (ignores high byte)
+         lda   <PD.SID,y      Get # sides
+         mul                  Calculate # tracks on drive (1 per head)
+         IFNE  H6309
+         decd                 Adjust to ignore track 0
+         ELSE
+         subd  #$0001
+         ENDC
+         lda   <PD.SCT+1,y    Get # sectors/track
+         sta   DD.TKS,x       Save in drive table
+         sta   <DD.SPT+1,x    Save in other copy in drive table
+         mul                  Calculate # sectors on drive (minus track 0)
+         pshs  x              Preserve drive table ptr
+         tfr   d,x            Move # sectors on drive to X
+         lda   <PD.T0S+1,y    Get # sectors on track 0
+         leax  a,x            Add that many sectors to total
+         lda   <PD.TYP,y      Get device type settings
+         anda  #%00000100     Mask out all but 512 byte sector flag
+         beq   L0550          Not 512 byte sector, skip ahead
+         IFNE  H6309
+         addr  x,x        Multiply by 2 (convert to 256 byte OS9 sectors)
+         ELSE
+         tfr   x,d
+         leax  d,x
+         ENDC
+L0550    tfr   x,d            Move # sectors to D
+         puls  x              Get back drive table ptr
+         std   DD.TOT+1,x     Save # sectors allowed on drive
+         lda   #UPDAT.+EXEC.  Owner's read/write/exec attributes
+         sta   DD.ATT,x       Set attributes for disk
+         lda   <PD.DNS,y      Get density settings
+         lsla                 Shift for DD.FMT
+         pshs  a              Preserve it a sec
+         lda   <PD.SID,y      Get # sides
+         deca                 Adjust to base 0
+         ora   ,s+            Merge with density settings
+         sta   <DD.FMT,x      Save in device table
+         clrb                 No error?
+         puls  pc,x           Restore original LSN & return
+
+         ELSE
+
+*****************************************************************
+*    NewDisk -- copyright 1985 by Dave Lewis.
+*    Released to public domain January, 1986
+*    Permission granted to copy and redistribute provided this
+*      header is included with all copies.
+*
+* This program is intended to replace the CCDisk module in the
+*   OS9Boot file on the OS-9 system disk. It is far more
+*   versatile than the disk driver provided with Color Computer
+*   OS-9, and is also slightly smaller (20 bytes or so).
+*   Some of its features are:
+*
+*  -Uses the device descriptor to set head step rate. Original
+*     had 30mS hard-coded in.
+*  -Handles double-sided disks.
+*  -Gets its track and side information from the disk so you
+*     can read and write disks in any format the drive can
+*     physically handle. You can use 40-track double sided disks
+*     and still read/write 35-track single side disks.
+*  -Performs some tests before attempting to use the disk.
+*     The original CCDisk would hang the system if you tried to
+*     access a drive without a disk in it (I know, I know - you
+*     don't have to say `DUMMY!' - but it happens). You can
+*     hang this one too but not as easily.
+*  -An 80-track double sided disk holds 720Kbytes of data.
+*     That's four and a half 35-track single siders.
+*  -All of this stuff is completely transparent once NewDisk is
+*     installed. NewDisk automatically senses the disk format
+*     and conforms to it. (within limits -- don't use non-OS9
+*     formats)
+*
+* One problem -- this program is not complete in itself. If you
+*   want to boot from a double-sided disk you will need my
+*   version of OS9Gen which will generate a double-sided system
+*   disk. Don't try it with the stock version; you'll have to
+*   reformat the disk to clean it up afterwards.
+*****************************************************************
+*           Copyright 1985 by Dave Lewis.
+*
+* UUCP address is loral!dml; in S. Cal. use ihnp4!sdcc3!loral
+*
+* I'm releasing this program to public domain. Copy it, share
+*   it, but don't you DARE sell it! I worked hard on it. Include
+*   this header with all copies.
+*
+* If you like this program, send me 5 bucks to encourage me to
+*   write more stuff - or at least to release it. If you send
+*   me 10 bucks I'll send you a good (Dysan) double side disk
+*   formatted 35 track single side with both sourcecode and
+*   executable binary files of the following:
+*
+*   - NewDisk -- single or double sided disks, any number of
+*       tracks within reason, step rate set in device descriptor
+*   - OS9Gen -- rewritten version that automatically senses for
+*       single/double sided disk and puts all the boot data in
+*       the right places. Also enters the kernel file in the
+*       root directory, which makes Dcheck happy.
+*   - Separate -- breaks up your bootfile into its component
+*       modules for modification. Replace or remove any module
+*       individually.
+*   - Diskdescr -- sourcecode for an OS-9 disk device descriptor
+*       with EQUates at the beginning for step rate, #tracks,
+*       and single or double sided.
+*   - Documentation and procedure files for installing all of
+*       the above in most common system configurations.
+*   - Other stuff I've written that you may find useful.
+*
+*   Send to:
+*             Dave Lewis
+*             4417 Idaho  Apt. 4
+*             San Diego CA 92116
+*****************************************************************
+*
+*
+*  Copyright 1985 by Dave Lewis
+*                4417 Idaho apt. 4
+*                San Diego, CA 92116
+*  Released to public domain January, 1986
+*
+*
+*
+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 eom,NAME,tylg,atrv,EXEC,STORG
+         FCB $FF Mode byte -- all modes
+NAME     FCS 'rb1773'
+         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 RWCMDX Execute command
+WAITWDRQ BITA >STATREG Wait until controller is
+         BEQ WAITWDRQ   ready to transfer 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 RWCMDX Execute command
+WAITVDRQ BITA >STATREG Wait until controller is
+         BEQ WAITVDRQ   ready to transfer data
+*
+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 RWCMDX Set up for sector read
+WAITRDRQ BITA >STATREG Wait for controller to find
+         BEQ WAITRDRQ   sector and start reading
+*
+READLOOP LDA >DATAREG Get data from controller
+         STA ,X+ Store in sector buffer
+         STB >DPORT Activate DRQ halt function
+         BRA READLOOP Loop until interrupted
+*
+RWCMDX   LDX PD.BUF,Y Point to sector buffer
+         LDB DPRT.IMG,U Do a side verify using the
+         BITB #$40   DPORT image byte as a side
+         BEQ WTKCMDX   select indicator
+         ORA #8 Compare for side 1
+WTKCMDX  STA >COMDREG Issue command to controller
+         LDB #$A8 Set up DRQ halt function
+         ORB DPRT.IMG,U OR in select bits
+         LDA #2 DRQ bit in status register
+         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
+         BSR WTKCMDX Execute write track command
+         LBSR WAITWDRQ 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
+         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   STA >COMDREG Execute command in A
+         CLRA Clear carry flag
+         BSR WAIT50MS Wait while command runs
+         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
+*
+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
+*
+         ENDC
+
+         emod
+eom      equ   *
+         end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/level1/modules/rb1773desc.asm	Tue May 18 01:26:19 2004 +0000
@@ -0,0 +1,66 @@
+********************************************************************
+* rb1773desc - rb1773 Device Descriptor Template
+*
+* $Id$
+*
+* Edt/Rev  YYYY/MM/DD  Modified by
+* Comment
+* ------------------------------------------------------------------
+
+         nam   rb1773desc
+         ttl   rb1773 Device Descriptor Template
+
+* Disassembled 98/08/23 17:09:41 by Disasm v1.6 (C) 1988 by RML
+
+         ifp1  
+         use   defsfile
+         endc  
+
+tylg     set   Devic+Objct
+atrv     set   ReEnt+rev
+rev      set   $00
+
+DNum     set   0
+Type     set   TYP.CCF+TYP.5
+Density  set   DNS.MFM
+Step     set   STP.6ms
+Cyls     set   35
+Sides    set   1
+Verify   set   1
+SectTrk  set   18
+SectTrk0 set   18
+Interlv  set   3
+SAS      set   8
+
+         mod   eom,name,tylg,atrv,mgrnam,drvnam
+
+         fcb   DIR.!SHARE.!PEXEC.!PWRIT.!PREAD.!EXEC.!UPDAT. mode byte
+         fcb   HW.Page    extended controller address
+         fdb   $FF40      physical controller address
+         fcb   initsize-*-1 initalization table size
+         fcb   DT.RBF     device type:0=scf,1=rbf,2=pipe,3=scf
+         fcb   DNum       drive number
+         fcb   Step       step rate
+         fcb   Type       drive device type
+         fcb   Density    media density:0=single,1=double
+         fdb   Cyls       number of cylinders (tracks)
+         fcb   Sides      number of sides
+         fcb   Verify     verify disk writes:0=on
+         fdb   SectTrk    # of sectors per track
+         fdb   SectTrk0   # of sectors per track (track 0)
+         fcb   Interlv    sector interleave factor
+         fcb   SAS        minimum size of sector allocation
+initsize equ   *
+
+         IFNE  DD
+name     fcs   /DD/
+         ELSE
+name     fcb   'D,'0+DNum+$80
+         ENDC
+mgrnam   fcs   /RBF/
+drvnam   fcs   /rb1773/
+
+         emod  
+eom      equ   *
+         end   
+