 ttl UniFLEX Disk Formatter
 sttl X-12+ WD 1001 5" Winchester Bootstrap
 pag
 info Bootstrap for X-12+/WD1001 Version 2.01; 8/10/83

* UniFLEX Bootstrap Loader for WD 1000 5" Winchester

 global uboot,DCtbl

* Equates
ffmap equ 17 file map offset in fdn
bhxfr equ 10 transfer address offset in header
BHDSIZ equ 24 binary file header size
*
* equates and addresses
*
*
IFR29 equ $E8AD 6522 interrupt flag reg
wd1000 equ $E8E0 Western Digital Interface
wd_data equ wd1000+0 data register
wd_error equ wd1000+1 error register
wd_sec_num equ wd1000+3 sector number
wd_cyl_low equ wd1000+4 cylinder (low part)
wd_cyl_hi equ wd1000+5 cylinder (high part)
wd_sdh equ wd1000+6 size/drive/head
wd_status equ wd1000+7 status register
wd_cmd equ wd_status command register
*
wd_read equ %00101000 read sector with DMA

* Temporary storage

 base $00E0 Page 0 data

r0 rmb 4 divide work registers
r1 rmb 2
rmndr rmb 2
btdate rmb 4
direct rmb 1
mapptr rmb 2
fdnbkn rmb 3
entrys rmb 2
xfradr rmb 2

* Special locations

corcnt equ $13
lstmem equ $14

DATMAP equ $F40A Map for $A000
BLKHOLE equ $FF Black hole in map
DATSENSE equ $00 Sense of data in DAT

old_org equ $B000 org of loader as loaded by ROM
new_org equ $B800 new org of loader

 base new_org+512
buffer rmb 512
map rmb 512
*
 data

* Lookup "uniflex" in directory

uboot lbra uboot0 *** For SWTPC! ***
* filename for booting
btname fcc 'uniflex'
 fcb 0,0,0,0,0,0,0
*
uboot0
*
* Relocate loader from "old_org" to "new_org"
*
 ldx #old_org
 ldu #new_org
00 ldd ,x++ move loader text
 std ,u++
 cmpx #old_org+512
 blo 00b
 lbra (uboot1-old_org)+new_org
*
uboot1 lda $010A check block $A000 mapped in
 cmpa #BLKHOLE black hole?
 bne uboot2
 dec corcnt decrease number of pages available
 ldx lstmem pick up last page pointer
 lda ,-x get a page
 stx lstmem
 sta $010A set up map
 sta DATMAP
uboot2 ldd #1 root directory fdn no.
 lbsr fdnblk read in fdn
 ldd 7,y find size of directory
 lbsr divby8
 lsra
 rorb
 std entrys save entry count
read1 lbsr rdblk read data block
 lbne noboot exit if error
lookup leax 2,u point to filespec
 leay <btname,pcr point to boot file name
 ldb #14 set name length
cmpnam lda 0,x+
 cmpa 0,y+ is this boot file entry?
 bne nxtent if not, skip to next
 decb
 bne cmpnam
 ldd 0,u found it, get fdn
 bra load go load uniflex
nxtent ldx entrys
 leax -1,x decrement count
 stx entrys end of directory?
 lbeq noboot error if so
 leau 16,u point to next entry
 cmpu #buffer+512 past current block?
 bne lookup check entry if not
 bra read1 else, get another block


* Load UniFLEX

load bsr fdnblk read in uniflex fdn
 ldx mapptr point to fdn map
 leax 13*3,x skip map
 ldb #4 set count
 ldy #btdate point to date store
lode22 lda 0,x+ save the fdn date
 sta 0,y+
 decb
 bne lode22
 lbsr rdblk read 1st block of the file
 bne noboot exit if error
 ldd bhxfr,u get transfer address
 std xfradr save it
 leau BHDSIZ,u skip binary file header
getrc1 bsr getchr get record length in x
 tfr b,a
 bsr getchr
 cmpd #0 terminator?
 beq done start uniflex if so
 tfr d,x
 bsr getchr get load address in y
 tfr b,a
 bsr getchr
 tfr d,y
getrc2 bsr getchr get a data byte
 stb 0,y+ put in memory
 leax -1,x decrement the count
 bne getrc2 loop if not end of record
 bra getrc1 else, get next record

* Uniflex is loaded, begin execution

done ldx #btdate transfer date to uniflex
 ldy $5002 get boot date vector
 ldb #4 set count
done2 lda 0,x+
 sta 0,y+
 decb
 bne done2
 jmp [xfradr] jump to transfer address

* Divide contents of D by 8

divby8 lsra
 rorb
 lsra
 rorb
 lsra
 rorb
 rts

* Get single character from binary file

getchr cmpu #buffer+512 more data in buffer?
 bne getch2 skip if so
 pshs a,x,y
 bsr rdblk else, read another block
 puls a,x,y
 bne nbootx exit if error
getch2 ldb 0,u+ get character, advance ptr
 rts

* Uniflex file was not found

nbootx puls d fix stack
noboot rts return to monitor ROM

* Read fdn specified in D

fdnblk pshs d save fdn number
 addd #15 convert to block number
 bsr divby8
 std fdnbkn+1 save fdn block #
 clr fdnbkn
 ldy #fdnbkn
 bsr mread read a block
 puls d restore fdn number
 bne nbootx exit if error
 decb calculate buffer offset
 andb #$07
 lda #64
 mul offset=(fdn&7)*64
 addd #map
 tfr d,y fdn pointer in y
 addd #9 point to ffmap
 std mapptr save map pointer
 lda #10 get direct block count
 sta direct initialize indirect flag
 rts

* Read a block from file

rdblk tst direct a direct block?
 beq chgind change to indirect
 dec direct dec. direct count
 ldy mapptr get file map pointer
 ldx #buffer setup buffer address
 bsr xread read the sector
 pshs cc
 sty mapptr
 puls cc,pc

chgind ldy mapptr get file map pointer
 bsr mread read block of indirects
 bne nbootx exit if error
 stu mapptr reset file map pointer
 lda #128 set new direct count
 sta direct
 bra rdblk now read data block

* Read the specified map block

mread ldx #map address of buffer for block

* Read a single sector
*  X - Buffer Address
*  Y - Block # Pointer

xread leau 0,x save X pointer
 ldb ,y+ calculate disk address
 clra
 std r0
 ldd ,y++
 std r0+2
 ldd #17 Sectors/Track
 std r1
 bsr ldiv
 ldb rmndr+1 get sector #
 incb adjust (no sector 0)
 stb wd_sec_num
 ldb DCtbl+2,pcr get number of heads
 clra
 std r1
 bsr ldiv
 ldb rmndr+1 get head #
 orb #$20+$80 set for 512 byte sectors, ECC
 stb wd_sdh
 ldd r0+2
 sta wd_cyl_hi
 stb wd_cyl_low
 lda #wd_read send command
 sta wd_cmd
loop lda wd_status get the wd status
 bita #$80 busy?
 bne loop loop until finished
 bita #1 error bit set?
 bne badext
 bita #8 drq?
 beq badext if not, exit out
 clrb set counter
loadlp lda wd_data get the data byte
 sta 0,x+ and store in buffer
 lda wd_data get the next data byte
 sta 0,x+
 decb decrement the counter 1 pair
 bne loadlp and loop until finished
 lda #$7F clear interrupt stuff
 sta IFR29
 clra set ending status good
 rts

badext ldb #$7F clear interrupt stuff
 ora #1 set error bit in acc a
 rts and return to caller

*
* 'Ldiv' divides a 32 bit number (r0 -> r0+3) by a 16 bit
* number (r1 -> r1+1) and produces a 32 bit result
* in r0 and a 16 bit remainder in 'rmndr'.
*

ldiv ldb #33 set loop counter
 pshs b
 ldd #0 do init
 std rmndr
 bra ldiv2
ldiv1 ldd rmndr do subtraction
 subd r1
 bcs ldiv2 rmndr > r1 ?
 std rmndr set new work value
ldiv2 rol r0+3 do shifting
 rol r0+2
 rol r0+1
 rol r0
 rol rmndr+1
 rol rmndr
 dec 0,s dec the loop count
 bne ldiv1
 com r0 compliment the result
 com r0+1
 com r0+2
 com r0+3
 lsr rmndr adjust the remainder
 ror rmndr+1
 puls b,pc return

*
* delay - delay for a short while
*
delay ldx #500
10 leax -1,x
 bne 10b
 rts


DCtbl fdb 306 Cylinders
 fcb 6 Heads
 fdb 306 Begin reduced write
 fdb 306 Begin write precompensation
 fcb 11 Max ECC burst

* filler bytes

 if (*-uboot)>512
 err 'Bootstrap overflow'
 else
 rzb 512-(*-uboot)
 endif
 end
