Retrocomputing

Boot module for DC3 floppy disk drive

The Boot module is called by part the of the kernel to load the remaining modules. Boot usually contains a minimal device driver for a disk drive. It loads the first sector of the disk, then looks for the location of "OS9Boot" and loads it into memory.

         opt  l
         nam Swtpc Dc-3 controller boot source

         opt  -c

         use  defsfile

         ttl Boot Module
         pag
*******************************************************************
*
*                 Microware Systems Corporation
*
*
*       Os-9 Swtpc Dc-3 Disk Boot Module
*
*       Software To Boot Swtpc Dc-2, And Dc-3 Disk Controllers
*
*                         Revised By
*                     William G. Phelps
*
*
*       This Controller Uses The Fdc1 1771 Lsi Disk Controller
*
**********************************************************************






***************************************************************
*
* Disk Boot Module Header
*
*
         mod  BTEND,BTNAM,SYSTM+OBJCT,REENT+1,BTENT,BTSTA
BTNAM    fcs  "Boot"

         fcb  1          Edition telltale byte
*******************
* Revision History
* edition 0: prehistoric
* edition 1: all use statements converted to use defsfile
*            copyright removed from object file
*            disktype set Dc3 added
*******************

         pag
Steprt   fcb  0

*********************************************************************
*
* Static Storage
*
*
         org  0
V.SEL    rmb  2          Drive select reg addr.
V.CMDR   rmb  2
V.TRKR   rmb  2
V.SECR   rmb  2
V.DATR   rmb  2
V.EFLG   rmb  1          Set "e" for head settle time
V.SIDE   rmb  1          Current side; 0:=side 0
V.TMP    rmb  1          Temporary save byte
V.BUF    rmb  2          Local buffer addr
V.TRCK   rmb  1          Current track
V.DRV    rmb  1          Drive select reg save
BTSTA    equ  .          Total static requirement


*
* Fd1771 Commands
*

F.REST   equ  $0B        Restore command
F.SEEK   equ  $1B        Seek command
F.STPI   equ  $4B        Step in one track command
F.READ   equ  $88        Read sector command
F.WRIT   equ  $A8        Write sector command
F.TYP1   equ  $D0        Force type 1 status
F.WRTR   equ  $F4        Write track command
         pag
****************************************************************
*
* Initialize The I/O Port
*
*  Input: (U)= Pointer To Global Storage
*
*  On Exit: (A) Modified
*           (X) Modified
*           (Y) Unchanged
*           (U) Unchanged
*
BTENT    clra
         ldb  #BTSTA     Get size of needed static
INILUP   pshs a
         decb
         bne  INILUP
         tfr  s,u        Point "u" to static
         ldx  #DPORT     Point to controller addr
         stx  V.SEL,U    Address of drive select reg.
         leax 4,X        Address of command register
         stx  V.CMDR,U
         lda  #F.Typ1
         sta  0,x        Inz controller chip
         lbsr Delay      Wait for 1771
         lda  0,x        Read controller status to clear it.
         leax 1,X        Address of track register
         stx  V.TRKR,U
         leax 1,X        Address of sector register
         stx  V.SECR,U
         leax 1,X        Address of data register
         stx  V.DATR,U
         lda  #$FF
         sta  V.TRCK,U   Inz to high track count

*        Fall thru to do the boot
         pag
*******************************************************************
*
* Bootstrap System From Disk
*
*         (U)= Pointer Global Storage
*
*  Output: (D)= Length Of Bootstrap Data
*          (X)= Address Of Start Of Boot Data
*          (Y) Unchanged
*          (U) Unchanged
*
LBOOT    pshs D,X,U      Save registers
         clra
         clrb
         ldy  #1
         ldx  D.FMBM
         ldu  D.FMBM+2
         OS9  F$SchBit   Search for buffer spot
         bcs  BOOTE1     Problem no mem
         exg  a,b        Convert page no. to addr
         ldu  4,s        Restore "u"
         std  V.BUF,u    Save buffer addr for use
         clrb
         ldx  #0         Get sector zero
         bsr  READSK
         bcs  BOOTE1     Branch if can't
         ldd  DD.BSZ,Y   Get bootstrap size
         std  0,S        Return to caller
         OS9  F$SRqMem   Get boot memory
         bcs  BOOTE1     Branch if none
         stu  2,S        Return to caller
         ldu  4,S        Get static storage
         ldx  2,s        Get mem addr
         stx  V.BUF,u
         ldx  DD.BT+1,Y  Get boot sector
         ldd  DD.BSZ,Y   Get boot size
         beq  BOOT2
BOOT1    pshs D,X        Save size, sector number
         clrb
         bsr  READSK     Read sector
         bcs  BOOTER
         puls D,X        Retrieve size, sector number
         inc  V.BUF,U    Move buffer ptr
         leax 1,X        Up sector number
         subd #$100      Subtract page read
         bhi  BOOT1      Branch if more
BOOT2    clra            CLEAR Carry
         puls d
         bra  Bootz


BOOTER   leas 4,S        Return scratch
BOOTE1   leas 2,S        Return scratch
Bootz    puls x,u
         leas BTSTA,s    De-allocate static fm stack
         rts
         pag
*********************************************************
*
* Restore Drive To Track Zero
*
*  Input: (Y)= Pointer To Path Descriptor
*         (U)= Pointer To Global Storage
*
*  If Error: (B)= Error Code & Carry Is Set
*
* Note:  We Are Stepping In Several Tracks Before
*        Issuing The Restore.  As Suggested In The
*        Application Notes.
*
RESTOR   clr  V.Drv,u
         clr  V.TRCK,U   Old track = 0
         lda  #5         Repeat five times
RESTR2   ldb  #F.STPI    Step in command
         pshs A
         lbsr WCR0       Issue command, delay & wait for done.
         puls A
         deca            DONE Stepping?
         bne  RESTR2     ...no; step again.
         ldb  #F.REST    Restore command
         lbra WCR0
         pag
*************************************************************
*
* Read Sector Command
*
* Input: B = Msb Of Logical Sector Number
*        X = Lsb'S Of Logical Sector Number
*        Y = Ptr To Path Descriptor
*        U = Ptr To Global Storage
*
* Output: 256 Bytes Of Data Returned In Buffer
*
* Error: Cc=Set, B=Error Code
*
READSK   lda  #$91       Error retry code
         cmpx #0         Is this sector zero?
         bne  RDSK3      Branch if not
Read0    bsr  RDSK3      Read sector into buffer
         bcs  Retrn1
         ldy  V.BUF,u    Point "y" to dd. info
         clrb
Retrn1   rts


RDSK1    bcc  RDSK3      Retry without restore
         pshs D,X
         bsr  RESTOR     Drive to tr00
         puls D,X
RDSK3    pshs D,X
         bsr  READSC     Read sector
         puls D,X
         bcc  Retrn1     Return if no error
         lsra            DONE?
         bne  RDSK1      ...no; retry.
*
* Fall Through To Try One Last Time
*
READSC   bsr  PHYSIC     Move head to track
         bcs  Retrn1
         ldx  V.BUF,u    Point to buffer
         orcc #IRQMask+FIRQMask Disable interrupts
         ldb  #F.READ    Read sector command
         lbsr WCR        Issue command
         pshs Y,U        Save regs
         ldy  V.CMDR,U
         ldu  V.DATR,U
         bra  READS3
         pag
************************************************************
*
* Read Loop
*
READS2   lda  ,U         Get data
         sta  ,X+        Store it
READS3   ldb  ,Y         Get status
         bitb #%00000010 Data req?
         bne  READS2     ..yes; honor it.
         bitb #%00000001 Done?
         bne  READS3     ...no; try again.


         puls Y,U        Restore regs
         bitb #%00000100 Lost data?
         bne  RDERR      ..yes; return it.
         bra  STCK


RDERR    comb
         ldb  #E$Read
         rts
         pag
**************************************************************
*
* Convert Logical Sector Number To Physical Track And Sector
*
*  Input:  B = Msb Of Logical Sector Number
*          X = Lsb'S Of Logical Sector Number
*  Output: A = Physical Track Number
*          Sector Reg = Physical Sector Number
*  Error:  B = Error Code, W/Carry Set
*

PHYERR   comb
         ldb  #E$SECT    Error: bad sector number
         rts

PHYSIC   clr  V.DRV,u
         clr  V.SIDE,u
         tstb            CHECK Sector bounds
         bne  PHYERR     msb must be zero
         tfr  X,D        Logical sector (os-9)
         cmpd #0         Logical sector zero?
         beq  PHYSC7     ..yes; skip conversion.
         cmpd DD.TOT+1,Y Too high sector number?
         bhs  PHYERR     ..yes; sorry
         stb  V.TMP,U    Save (b)
         clrb
         pshs B          Will be track number
         ldb  DD.FMT,Y
         lsrb            SHIFT Side bit to carry
         ldb  V.TMP,U    Restore (b)
         bcs  PHYSC4     Bra if double sided
         dec  0,S
PHYSC2   inc  0,S
         subb DD.TKS,Y   Subtract one track worth of sectors
         sbca #0
         bcc  PHYSC2     Repeat until less than 1 track size
         bra  PHYSC5
PHYSC3   com  V.SIDE,U   Switch sides
         bne  PHYSC4     Skip track inc if side 1
         inc  0,S
PHYSC4   subb DD.TKS,Y
         sbca #0
         bcc  PHYSC3     Repeat until less than 1 trk
PHYSC5   addb DD.TKS,Y   Add back for sector number
         puls A          Desired track.
PHYSC7   stb  [V.SECR,U] Put sector (b) in sector reg
* Fall thru to do actual seek
         pag
**************************************************************
*
* Move Head To New Track
*
* Update Track Table With
* The Current Track
*
* Load The Track Register With The
* Old Track
*
* Input:
*   A = New Track
*   B = Seek Function Code (F.Seek)
* Output:
*   B = Contents Of Fd1771 Status Reg
*   A,X = Destroyed
*

SETTRK   ldb  V.SIDE,U   Get side info
         andb #%01000000 Mask all but needed bit
         orb  V.DRV,U    Mask into drive select
         stb  V.DRV,U    Save it
         ldb  V.TRCK,U   Get old track
         stb  [V.TRKR,U] Put old track in trk reg
         cmpa V.TRCK,U   Same track?
         beq  SETRK9     ..yes; skip seek.
         sta  V.TRCK,U   Update with new track
         sta  [V.DATR,U] Put new trk in data reg
         ldb  #F.SEEK    Command
         bsr  WCR0       Issue command
         lda  #4
         sta  V.EFLG,U
Setrk9   clrb
         rts
         pag
***********************************************************
*
* Check Status For Error Conditions
*
*  Input: (B)= Status Of Fd1771
*
*  If Error: (B)= Error Code & Carry Is Set
*
*  If No Error: Carry Is Clear
*
STCK     bitb #%10000000 Drive ready?
         bne  ERNRDY     ..no; error
         bitb #%00010000 Seek error?
         bne  ERSEEK     ..yes; return error
         bitb #%00001000 Check sum ok?
         bne  ERRCRC     ..no; return error
         clrb
         rts



ERNRDY   comb
         ldb  #E$NotRdy  Error: drive not ready
         rts

ERSEEK   comb
         ldb  #E$SEEK    Error: seek error
         rts

ERRCRC   comb
         ldb  #E$CRC     Error: bad check sum
         rts
         pag
****************************************************************
*
*
* Write Command Register
*
*
*   1 - Will Add Step Rate To Seek Commands When Wcr0 Called
*   2 - Issues Command To Controller Chip
*   3 - Will Wait For Status "Not Busy" If Wcr0 Called
*
*

WCR0     eorb Steprt,pcr Add step rate to command
         bsr  WCR        Issue command & delay
WCR02    ldb  [V.CMDR,U] Get status
         bitb #%00000001 Busy?
         bne  WCR02      ..yes; wait for it.
         rts



WCR      lda  V.DRV,U
         sta  [V.SEL,U]  Select drive
         orb  V.EFLG,U
         clr  V.EFLG,U
         stb  [V.CMDR,U] Issue command


DELAY    bsr  DELAY1
DELAY1   bsr  DELAY2
DELAY2   bsr  DELAY4
DELAY4   nop
         rts

         emod

BTEND    equ  *

         end