           ttl     SBC Floppy Disk Bootstrap

*
.   disk bootstrap program
.
loadipl:   proc

bootsec    equ     1                   sector number of ipl record
retries    equ     8                   set max number of retries
seclen     equ     512                 disk sector length
bootadr    equ     userseg<<12         logical bootstrap address
DMF        equ     $E8C0               address of 1797 Controller
*
.   SBC 179x disk controller definitions
.
command    equ     DMF+$000            disk controller command register
status     equ     DMF+$000            disk controller status register
track      equ     DMF+$001            disk controller track register
sector     equ     DMF+$002            disk controller sector register
data       equ     DMF+$003            disk controller data register
*
.   SBC 179x disk controller command definitions
.
forceint   equ     %11011000           force interrupt command
restore    equ     %00001001           restore command
read       equ     %10001100           single sector read command
*
.   DMF-X 179x disk controller status bits
.
drdy       equ     %10000000           1 => drive not ready
skerr      equ     %00010000           1 => seek error
nrf        equ     %00010000           1 => no record found error
crc        equ     %00001000           1 => crc error
lsd        equ     %00000100           1 => lost data error
dbusy      equ     %00000001           1 => controller busy
rd_mask    equ     %10011100           read error mask
*
.   SBC drive select latch definitions
.
via29      equ     $E8A0               VIA containing drive sel, etc
ORB        equ     via29+0             output register B
ORA        equ     via29+1             output register A
DDRB       equ     via29+2             data dir reg A side
DDRA       equ     via29+3             data dir reg B side
PCR        equ     via29+12            periph control register
IFR        equ     via29+13            interrupt flag register
IER        equ     via29+14            interrupt enable register

density    equ     %00100000           select single density
select     equ     %11001000           ds 0, head load, write precomp enab.
*
.   SBC funny DRQ / BUSY status latch (ORB / IRB)
.

via_drq    equ     %01000000           drq bit
via_intrq  equ     %10000000           intrq bit from 1797


*
.   local variable definitions
.
densel     loc     1                   Density Select Flag
retryc     loc     1                   Boot Read Retry Counter
*
.   reset the stack and set up direct addressing
.
           scc     irq,firq            disable interrupts in boot
           mark    dpr                 save DPR value and mark stack
           aloc                        allocate local variables
           lda     #DMF>>8             load the msp of the address
           tfr     a,dpr               set direct addressing
           setdp   DMF                 and tell the assembler
*
.   initialize the VIA for this type of thing
.
           lda     #%11111111          set a side direction
           sta     DDRA
           lda     #%11001111          motor on, no drives selected
           sta     ORA
           lda     #%00000000          set b side for all inputs
           sta     DDRB
           lda     #%11110101          set up CA CB control lines
           sta     PCR
           lda     #%01111111          do not enable VIA interrupts
           sta     IER
           sta     IFR                 clear any pending stat in IFR
*
.   set up density select and retry counter
.
dodisk     lda     #select             set select for drive zero
           sta     densel              stuff the density select
           lda     #retries            load number of retries
           sta     retryc              stuff the retry counter
*
.   select the drive and force 179x to quit whatever
.
tryboot    lda     densel              get the drive select byte
           sta     ORA                 stuff into drive select latch
           lda     #forceint           load a force interrupt command
           bsr     diskcmd             send the command to te disk
*
.   read 179x status latch and see if drive comes up ready
.
           ldy     #28000              allow up to 3 seconds for drive ready
check      bsr     delay               delay 174 uSeconds
           lda     status              check 179x drive ready status bit
           bpl     dorest              if ready, go do the restore
           leay    -1,y                decrement delay count
           bne     check               loop if not so
           bra     loadxit
*
.   restore the drive and wait for it to complete
.
dorest     lda     #restore            load a restore command
           bsr     diskcmd             and attempt to restore the drive
waitrst    lda     status              pick up 179x status register
           bita    #dbusy              check for the busy bit
           bne     waitrst             loop until busy goes away
           bita    #skerr              check for seek error
           bne     loadxit             if so, don't try to boot
*
.   now fire up 179x controller to do a single sector read
.
           ldd     #bootsec            load boot sector number
           std     track               set track number to zero
           lda     #read               load single sector read
           bsr     diskcmd             and fire up the controller
*
.   set up the  count and address registers
.
           ldx     #bootadr            load boot address
           ldy     #seclen             load sector length
*
.   programmed i/o read of the sector
.
ddread     lda     ORB                 get the funny status bytes
           bmi     ddrdata             if negative, DRQ request
           beq     ddread              if zero, still busy
           bra     checkit             go to completion loop
ddrdata    lda     data                load data byte from 1797
           sta     0,x+                and cram into buffer
           leay    -1,y                decrement the count
           bne     ddread              and loop for more data if necessary
           bra     checkit
*
.   no record found probably indicates wrong density, retry it
.
retryit    ldb     densel              pick up the drive select code
           eorb    #density            invert the density bit
           stb     densel              stuff back in the stack
           dec     retryc              decrement the retry counter
           bne     tryboot             if still some, retry it
*
.   go here if the load failed
.
loadxit    ldb     #forceint           force an interrupt
           stb     command             write into the command register
           ldb     #%00000111          deselect floppy drives
           stb     ORA                 to turn off the lights
           lda     #%01111111
           sta     IFR                 clear any pending stat in IFR
           ccc     z                   indicate load has failed
           exit    dpr
*
.   boot has completed - check for any sicknesses along the way
.
checkit    lda     status              pick up disk controller status
           bita    #dbusy
           bne     checkit
           bita    #crc+lsd+drdy       test for error conditions
           bne     loadxit             exit if error on boot sector
           bita    #nrf                check for improper density
           bne     retryit             if that's it, retry it
*
.   boot complete, set up stuff and exit
.
           lda     densel              set up to reselect the drive
           sta     ORA                 for the internal boot
           ldx     #bootadr            load bootstrap address
           tst     status              clear 1797 interrupts
           lda     #%01111111
           sta     IFR                 clear any pending stat in IFR
           clra                        set equal to show boot complete
           ldb     0,x                 pick up first byte of bootstrap
           cmpb    #$16                check for long branch instr
           exit    dpr
*
.   send a command to the 179x and wait for it to respond
.
diskcmd    sta     command             store the disk command
delay      lda     #32                 set up a delay counter
del        deca                        decrement the delay count
           bne     del                 hang in there for the count
           rts

           setdp   0

           end
