conv
; conv.dis - disassembly of Convergent Technologies Miniframe Boot ROM's
;
; This is the "B" rom set (there is another set called "A" - newer ?)
;
; Annotation begun 8/14/89 T. Trebisky
; ttrebisky@as.arizona.edu
;
0x800000: 00005f00 ; Stack pointer
0x800004: 00800024 ; PC
0x800008: 008003f0 ; Initialize disk
0x80000c: 008006a2 ; Read
0x800010: 0080068a ; Write
0x800014: 00800696 ; Format
0x800018: 00800398 ; Find superblock pointer
0x80001c: 008003e4 ; Recalibrate and initialize disk
0x800020: 0
; OK here we go, first write to the GCR (0x450000), turning off all 4 LED's,
; disable bus-errors, and turn off the ROM bit to allow access to RAM
;
; GCR is just the high 8 bits: EPER4310--------
; E = 1 enables NMI and BERR interrupts
; P = 1 enables Parity error interrupts
; E = 0 is even parity ( 1 = odd is normal )
; R = 0 forces ROM access (hides RAM), system boots up this way
; 4310 = set low to turn on corresponding LED (0 is bottom, near connectors)
0x800024: movw #0x3f00,0x450000:l
; Now initialize the "system" 8253, The idea is to keep track of lost time
; in the boot ROM so as to keep system clock up to date.
; Notice that the 8253 is slow and cannot be accessed on successive cycles,
; this is the reason for the "nop" instructions between accesses.
;
; 0x74 = CW for counter 1 - lsb then msb, Mode 2 binary
; 0xb6 = CW for counter 2 - lsb then msb, Mode 3 binary
;
; The 8253 has 3 counter/timers, Timer 0 is not used here (but can be
; programmed to interrupt as "fast timer" on 8259 priority 4).
; Timer 0 and 1 are fed a 76,800 Hz clock (REFCLK), having Timer 1 divide
; it by 500 hex (1280) yields a 60 Hz output which can be enabled to be
; a level 6 autovector. This output is fed to Counter 2, which just counts
; the ticks and can be read by software, it's output is not connected anywhere.
0x80002c: movw #0x74,0xc00006:l
0x800034: nop
0x800036: movw #0xb6,0xc00006:l
0x80003e: nop
; Load 8253 counter 2 with zeros
0x800040: clrw 0xc00004:l
0x800046: nop
0x800048: clrw 0xc00004:l
0x80004e: nop
; Load 8253 counter 1 with 0x0500
0x800050: movw #0,0xc00002:l
0x800058: nop
0x80005a: movw #5,0xc00002:l
; Initialize the first 6 Map registers, each one maps a 4K page (0-fff)
; so this establishes a transparent mapping for 0-5fff (including the stack).
0x800062: movw #0x2000,0x400000:l
0x80006a: movw #0x2001,0x400002:l
0x800072: movw #0x2002,0x400004:l
0x80007a: movw #0x2003,0x400006:l
0x800082: movw #0x2004,0x400008:l
0x80008a: movw #0x2005,0x40000a:l
; Save the processor registers (to 0-03f)
0x800092: moveml d0-d7/a0-a7,0:l
; Save GSR to 40-41
; Save BSR0 to 42-43
; Save BSR1 to 44-45
0x80009a: movl #0x40,a0
0x8000a0: movw 0x410000:l,a0@+
0x8000a6: movw 0x430000:l,a0@+
0x8000ac: movw 0x440000:l,a0@+
; Save Map registers, 000 (0x400000) to 46-47
; 3FF (0x4007fe) to 844-845
0x8000b2: movl #0x400000,a1
0x8000b8: movl #0x3ff,d0
0x8000be: movw a1@+,a0@+
0x8000c0: dbra d0,0x8000be
; copy CDT (Crash Data Table) to 846-8c5
; Odd, it looks like 3f8 is a location in the page table just copied,
; but why is it used as a long pointer, that would grab two successive
; table entries and use them as a pointer (??!)
; At any rate, 0x20 long entries (0x80 = 128 bytes) get moved to 846-8C5.
0x8000c4: clrw 0x420000:l ; clear CSR
0x8000ca: movl 0x3f8:l,d0
0x8000d0: bclr #0,d0
0x8000d4: movl d0,a1
0x8000d6: movl #0x1f,d0
0x8000dc: movl a1@+,a0@+
0x8000de: dbra d0,0x8000dc
; check CDT for proper CDT signature ( 'EPJR' )
; if signature is wrong, assume power-up reset boot
0x8000e2: clrw 0x420000:l ; clear CSR
0x8000e8: movl #0x846,a0 ; first long in CDT
0x8000ee: cmpl #0x45504a52,a0@+
0x8000f4: bnes 0x800124 ; power up will jump
; from here, must be software requested (or erroneous) reset
0x8000f6: tstb 0x854:l ; was this a panic?
0x8000fc: beqs 0x80010c
0x8000fe: movb #0,0x852:l ; 0x852 = 0
0x800106: jmp 0x800148:l
0x80010c: addl #8,a0
0x800112: movb #1,a0@+ ; 0x852 = 1
0x800116: movb #0,a0@+ ; 0x853 = 0
0x80011a: movb #0,a0@ ; 0x854 = 0
0x80011e: jmp 0x800148:l
; Set up the CDT area (this must be a power-up reset)
0x800124: movl #0x846,a0
0x80012a: movl #0x45504a52,a0@+
0x800130: movl #0,a0@+ ; 0x84a = 0
0x800136: movl #0,a0@+ ; 0x84e = 0
0x80013c: movb #2,a0@+ ; 0x852 = 2 *** flags power up
0x800140: movb #0,a0@+ ; 0x853 = 0
0x800144: movb #0,a0@ ; 0x854 = 0
; Initialize the Page Map, transparent, first 2Mb present, not accessed
0x800148: movw #0x2000,d3
0x80014c: movl #0x400000,a4
0x800152: movl #0x1ff,d0
0x800158: movw d3,a4@+
0x80015a: addqw #1,d3
0x80015c: dbra d0,0x800158
; Second 2Mb mapped as transparent, not present
0x800160: bclr #0xd,d3 ; turn off page present bit
0x800164: movl #0x1ff,d0
0x80016a: movw d3,a4@+
0x80016c: addqw #1,d3
0x80016e: dbra d0,0x80016a
; Turn on all LEDS (via GCR)
0x800172: movw #0x3000,0x450000:l
; set up the 8259
; 0x13 = ICW1 -- Edge triggered, 4 byte calls, single 8259
; 0x00 = ICW2 -- Vector base (T7-T3) = 00
; 0x01 = ICW4 -- Non-buffered 8086 mode
; 0xff = OCW1 -- all interrupt sources masked off
0x80017a: movw #0x13,0xc90000:l
0x800182: movw #0,0xc90002:l
0x80018a: movw #1,0xc90002:l
0x800192: movw #0xff,0xc90002:l
; same treatment for 8259 on the expansion board (non-existant for us)
0x80019a: movw #0x13,0xc70100:l
0x8001a2: movw #0,0xc70102:l
0x8001aa: movw #1,0xc70102:l
0x8001b2: movw #0xff,0xc70102:l
; ************************************************
; loop to recalibrate disks -
; stays here forever, until some disk recalibrates
;
; d0 = 2 (FD), 1 (HD1), 0 (HD0)
; ************************************************
0x8001ba: movw #0x3700,0x450000:l ; set LED pattern
0x8001c2: clrl d3 ; flag if any disk worked
0x8001c4: movl #2,d0 ; loop counter ( 2, 1, 0 )
0x8001ca: movl #0x2000,d1 ; BASE address for control area
0x8001d0: movl #0x3000,d2 ; buffer address for i/o
0x8001d6: jsr 0x8003e4:l
0x8001dc: cmpl #4,d7 ; 4 is error status
0x8001e2: beqs 0x8001e6 ; anything else is fine
0x8001e4: addql #1,d3 ; One worked !
0x8001e6: subql #1,d0 ; done ?
0x8001e8: bges 0x8001d6 ; keep going, do them all
0x8001ea: tstl d3 ; loop till someone works
0x8001ec: beqs 0x8001ba
; LED pattern "searching for dump area" (4 and 1 on)
; This is not pertinent for power-up boot
0x8001ee: movw #0x3500,0x450000:l
0x8001f6: cmpb #2,0x852:l ; power up boot ?
0x8001fe: beqs 0x80027a ; Yes !
; looking for dump area on disk (bypassed on power-up boot)
0x800200: movl #0x66,a0 ; offset for dump area pointer
0x800206: movl #0x2000,d1 ; BASE of control area pool
0x80020c: movl #0x3000,d2 ; buffer address
0x800212: jsr 0x800398:l ; get pointer to dump area
0x800218: tstl d7 ; find one ?
0x80021a: bnes 0x80027a ; no
; found a dump area,
; d4 = pointer to dump area on disk (in 1K block units)
; d5 = number of blocks in dump area (in 1K block units)
; d6 = device which had it
; now see how much memory we have to dump
0x80021c: clrl d2 ; start counter
0x80021e: movl d2,a6 ; first 128K block base = 0
0x800220: clrw 0x420000:l ; clear CSR
0x800226: movl a6,a5
0x800228: addl #0x1fffe,a5 ; check last word in 128K block
0x80022e: movw a5@+,d0 ; read from it (data irrelevant)
0x800230: movw 0x410000:l,d0 ; check GSR
0x800236: andw #0xffff8000,d0 ; Memory not present bit
0x80023a: beqs 0x80024e ; Zero means not present
0x80023c: cmpl #0x10,d2 ; End search at 2MB boundary
0x800242: beqs 0x80024e
0x800244: addql #1,d2 ; click counter
0x800246: addl #0x20000,a6 ; next 128K block
0x80024c: bras 0x800220
; OK - found end of memory, now work with number of 512 byte sectors
0x80024e: lsll #8,d2 ; Size of memory to dump
0x800250: lsll #1,d5 ; Size of dump area
0x800252: cmpl d2,d5 ; compare
0x800254: blts 0x800258
0x800256: movl d2,d5 ; dump area is bigger
0x800258: tstl d5 ; are we dumping anything
0x80025a: beqs 0x80027a ; no (dump area size = 0 ?)
; d5 = number of blocks to dump
; d6 = device to dump to
0x80025c: movl d6,d7 ; LED's get device code
0x80025e: orl #0x3000,d7 ; LED's (won't work in LSB)
0x800264: movw d7,0x450000:l ; LED's
0x80026a: movl #0,d3 ; start with this address
0x800270: lsll #1,d4 ; to this address on disk
0x800272: clrl d7
0x800274: jsr 0x80068a:l ; Call write routine
; Regular sequence for power-up boot is here
; Doing address test of memory
0x80027a: movl #0x3000,d0 ; start address test here
0x800280: movl d0,a0
0x800282: movl #0x80000,a6 ; end test before here
0x800288: movl d0,a0
0x80028a: movw #0x3800,d4 ; Bogus LED status
0x80028e: movw d4,0x450000:l ; "Mem Addr Test Fail"
0x800294: movw a0,a0@ ; Write addr at addr
0x800296: movl a0,d7
0x800298: cmpw a0@+,d7 ; Read it back
0x80029a: beqs 0x8002b0 ; Better be equal
0x80029c: orl #0x3800,d4 ; Address Test Failed !!
0x8002a2: movl d4,d7
0x8002a4: movw d7,0x450000:l ; Post status to LED
0x8002aa: stop #0x2700 ; Stop Dead
0x8002ae: bras 0x8002aa ; Really Dead!
0x8002b0: cmpl a0,a6
0x8002b2: bgts 0x800294 ; Loop thru range
; Second phase of address test, scan the range specified once again
; make sure data written is still there, unmangled.
0x8002b4: movl d0,a0 ; start address from above
0x8002b6: movw #0x3000,d4 ; LED status --
0x8002ba: movw d4,0x450000:l ; Address Test occurring
0x8002c0: movl a0,d7
0x8002c2: cmpw a0@+,d7
0x8002c4: bnes 0x80029c ; OOPS
0x8002c6: cmpl a0,a6
0x8002c8: bgts 0x8002c0
; Address Test done and successful
; Move 128 byte CDT area to 0x6ff80 - 0x6ffff
0x8002ca: movl #0x6ff80,a1 ; move it to here
0x8002d0: movl #0x846,a0 ; from here
0x8002d6: movl #0x7f,d0 ; this many (N-1)
0x8002dc: movb a0@+,a1@+ ; byte by byte
0x8002de: dbra d0,0x8002dc ; more
; LED status "searching for loader"
0x8002e2: movw #0x3600,0x450000:l
0x8002ea: movl #0x5a,a0 ; offset for loader pointer
0x8002f0: movl #0x2000,d1 ; BASE of control area pool
0x8002f6: movl #0x3000,d2 ; buffer address
0x8002fc: jsr 0x800398:l ; get pointer
0x800302: tstl d7 ; find one ?
0x800304: beqs 0x800310 ; YES !!
; LED status: FAIL3 - cannot find loader
; keep trying forever (maybe someone will put a disk in)
0x800306: movw #0x3a00,0x450000:l ; LED's
0x80030e: bras 0x8002ea ; keep trying
; LED status: Loading loader (4 and 3 on)
0x800310: movw #0x3300,0x450000:l
; Bravo! we have found a loadable image
; d4 = pointer to image on disk (in 1K block units)
; d5 = number of blocks in image (in 1K block units)
; d6 = device which had it
0x800318: movl #0x70000,d3 ; read image to here
0x80031e: lsll #1,d4 ; convert to 512 byte blocks
0x800320: lsll #1,d5 ; ditto - this many of them
0x800322: clrl d7
0x800324: jsr 0x8006a2:l ; Read the loader
0x80032a: tstl d7 ; Did it work ?
0x80032c: bnes 0x8002e2 ; NO
; LED status: Entering loader (4, 1 and 0 on)
0x80032e: movw #0x3400,0x450000:l
0x800336: clrw 0xc6002a:l ; Turn off floppy motor
0x80033c: jmp 0x70000:l ; <<< **** GO **** !!
0x800342: 0x4028 @( ; ?junk
0x800344: 0x2329 #) ; ?junk
0x800346: 0x7072 pr ; ?junk
0x800348: 0x6f6d om ; ?junk
0x80034a: 0x3232 22 ; ?junk
0x80034c: 0x0
0x80034e: 0x0
; *********************************************************
; Routine to read a disk "superblock" (first 1024 bytes on device)
; Validates what it reads (magic "UQVQ" in first word, and checksum)
; call with d6 = device (2=FD, 1=HD1, 0=HD0)
; returns with d7=0 if valid
; returns with d7=1 if anything goes wrong
; called from 8003ac, 8005ac
; *********************************************************
0x800350: movl #2,d5 ; Read this many 512 blocks
0x800356: movl 0x2004:l,d3 ; To this buffer address
0x80035c: clrl d4 ; From this disk address ( 0 )
0x80035e: movl #1,d7
0x800364: jsr 0x8006a2:l ; Read Em!
0x80036a: tstl d7 ; Did it work ???
0x80036c: bnes 0x800390 ; NO! Argh!
0x80036e: movl 0x2004:l,a1 ; Buffer address
0x800374: cmpl #0x55515651,a1@ ; 'UQVQ' must be first longword
0x80037a: bnes 0x800390 ; It isn't -- Argh!
0x80037c: jsr 0x8003d4:l ; calculate checksum
0x800382: movl #0,d7 ; valid return if we have:
0x800388: cmpl #-1,d5 ; valid checksum ?
0x80038e: beqs 0x800396 ; YES!
0x800390: movl #1,d7 ; error return
0x800396: rts
; *********************************************************
; Routine to search for pointer in a "superblock"
; Call with:
; a0 = offset to pointer info in superblock
; d1 = control area base (0x2000)
; d2 = buffer to use (0x3000)
; Returns:
; d4 = pointer to dump area on disk (in 1K block units)
; d5 = number of blocks in dump area (in 1K block units)
;
; called from 800212 -- to find dump area (with a0 = 0x66)
; called from 8002fc -- to find loader (with a0 = 0x5a)
; also external entry point
;
; BLOCK +0x5a - 0x5d = first block (1K) on disk for loader
; BLOCK +0x5e - 0x5f = number of blocks (1K) on disk for loader
;
; BLOCK +0x60 - 0x63 = first block (1K) on disk for block list
; BLOCK +0x64 - 0x65 = number of blocks (1K) on disk for block list
; ( but see some strangeness, 80060a )
;
; BLOCK +0x66 - 0x69 = first block (1K) on disk for dump area
; BLOCK +0x70 - 0x71 = number of blocks (1K) on disk for dump area
; *********************************************************
0x800398: movl #2,d0 ; begin loop with FD
0x80039e: addl d2,a0 ; point to item of interest
0x8003a0: jsr 0x8003f0:l ; initialize device info
0x8003a6: tstl d7 ; did it work ?
0x8003a8: bnes 0x8003c8 ; NO
0x8003aa: movl d0,d6 ; set device number
0x8003ac: jsr 0x800350:l ; read "superblock"
0x8003b2: tstl d7 ; did it work ?
0x8003b4: bnes 0x8003c8 ; NO
0x8003b6: movl a0@,d4 ; start pointer on disk
0x8003b8: movw a0@(4),d5
0x8003bc: andl #0xffff,d5 ; size of area on disk
0x8003c2: beqs 0x8003c8 ; forget it if size==0
0x8003c4: clrl d7 ; Got one!
0x8003c6: rts ; Done
0x8003c8: subql #1,d0 ; loop on (FD=2, HD1=1, HD0=0)
0x8003ca: bges 0x8003a0
0x8003cc: movl #2,d7 ; Noone had desired pointer
0x8003d2: rts ; Give up
; *********************************************************
; Calculate checksum on 1024 byte block
; called from 80037c and 800d2e
; Call with: a1 pointing to the buffer
; d5 returns the checksum
; *********************************************************
0x8003d4: clrl d5 ; initialize checksum
0x8003d6: movl #0x100,d4 ; this many 4 byte longwords
0x8003dc: addl a1@+,d5 ; add one
0x8003de: subql #1,d4 ; reduce count
0x8003e0: bnes 0x8003dc ; more
0x8003e2: rts ; done !
; *********************************************************
; This routine is called to recalibrate and initialize a disk
; Called from 8001d6 (initial recalibration loop),
; also external entry point
; *********************************************************
0x8003e4: moveml d0-d6/a0-a7,sp@-
0x8003e8: movl #1,d5
0x8003ee: bras 0x8003f6
; *********************************************************
; This routine is called to just initialize a disk
; Called from 8003a0 (superblock pointer finding routine),
; also external entry point
; *********************************************************
0x8003f0: moveml d0-d6/a0-a7,sp@-
0x8003f4: clrl d5
; common code for both entry points above
;
; 0x2000-3 holds base address (4 bytes) for IO control area allocation
; 0x2004-7 holds base address (4 bytes) for other gyrations
; 0x2008-9 holds DMA word count on completion (noone ever uses it)
; 0x200a-b holds error status on operation completion
; 0x200c-d holds HD error flags (from WD1010)
; 0x200e-11 holds count of errors (never initialized)
0x8003f6: clrw 0xc60036:l ; reset disk BIU
0x8003fc: movl d0,d6
0x8003fe: movl d1,0x2000:l ; only place this is set
0x800404: movl d2,0x2004:l ; only place this is set
0x80040a: jsr 0x800438:l ; set a0 (according to d6)
0x800410: cmpl #0,d0
0x800416: beq 0x800508 ; HD 0
0x80041a: cmpl #1,d0
0x800420: beq 0x80052a ; HD 1
0x800424: cmpl #2,d0
0x80042a: beqs 0x800494 ; floppy
0x80042c: movl #3,d7 ; Error - no such d0 allowed
0x800432: moveml sp@+,d0-d6/a0-a7 ; lots of people return here
0x800436: rts
; *********************************************************
; allocate an IO control area, based on the value in d6
; 0x426 is 0x26 byte prefix, then 0x400 buffer (1k byte)
; The base is fetched (long) from 0x2000
; BASE to BASE+0x0013 are used for other things (see above)
;
; d6 = 0 a0 = BASE + 0x0014 d7 = 0
; d6 = 1 a0 = BASE + 0x043A d7 = 0
; d6 = 2 a0 = BASE + 0x0860 d7 = 0
; d6 = any other value --- d7 = 3
; *********************************************************
0x800438: clrl d7 ; valid return (d7=0)
0x80043a: movl 0x2000:l,a0 ; get base address for alloc
0x800440: addl #0x14,a0 ; ( +0x14 )
0x800446: cmpl #0,d6
0x80044c: beqs 0x800470
0x80044e: addl #0x426,a0 ; ( +0x43A )
0x800454: cmpl #1,d6
0x80045a: beqs 0x800470
0x80045c: addl #0x426,a0 ; floppy ( +0x860 )
0x800462: cmpl #2,d6
0x800468: beqs 0x800470
0x80046a: movl #3,d7 ; Error (d7=3)
0x800470: rts
; Set up the 8259
; 0x13 = ICW1 -- Edge triggered, 4 byte calls, single 8259, need ICW4
; 0x58 = ICW2 -- Vector base (T7-T3) = 58 - 5F (Why?)
; 0x03 = ICW4 -- Auto EOI, Non-buffered 8086 mode
; 0xff = OCW1 -- all interrupt sources masked off
0x800472: movw #0x13,0xc90000:l
0x80047a: movw #0x58,0xc90002:l
0x800482: movw #3,0xc90002:l
0x80048a: movw #0xff,0xc90002:l
0x800492: rts
; *********************************************************
; Entry point for Floppy Disk
; only call is from 80042a above
; *********************************************************
0x800494: clrw 0xc60022:l ; FD reset off
0x80049a: movw 0xc60010:l,d0 ; read FD status (silly)
0x8004a0: clrw 0xc60028:l ; FD motor on
0x8004a6: jsr 0x800472:l ; setup 8259 (all disabled)
0x8004ac: movb #1,a0@(0x20) ; 0 = HD, 1 = FD
0x8004b2: movb #2,a0@(0x21) ; 0 = HD0, 1 = HD1, 2 = FD
; Sneaky place to hide a bit -- the following test looks at bit 0 in the
; "slow comm port status register" -- When that bit is zero, a floppy
; drive is connected to the floppy port (the hardware exists)
0x8004b8: movw 0xc30008:l,d7 ; SCOMM status port
0x8004be: andw #1,d7 ; FD present bit
0x8004c2: bne 0x800560 ; none there, return w/ d7=4
; Aha - a floppy is out there
0x8004c6: tstl d5 ; d5=1 on recalibrate
0x8004c8: beq 0x80056a ; not a recal, bypass
; Wait for floppy drive to come up ready
0x8004cc: movl #0x29810,d1 ; 170,000 decimal (timeout)
0x8004d2: movw 0xc60010:l,d0 ; floppy status
0x8004d8: btst #7,d0 ; check Not-Ready bit
0x8004dc: beqs 0x8004e2 ; Zero means Ready
0x8004de: subql #1,d1 ; count down (timeout)
0x8004e0: bgts 0x8004d2 ; check status again
; OK - the floppy is there and ready! (or the above loop timed out)
; Recalibrate the thing.
0x8004e2: jsr 0x800b0c:l ; set density
0x8004e8: movw #0,0xc60010:l ; Restore > floppy command
0x8004f0: jsr 0x800abe:l ; Wait for completion
0x8004f6: clrw 0xc60012:l ; write 0 to track register
0x8004fc: movl d0,d7 ; d0 holds status
0x8004fe: andl #4,d7 ; check TRACK0 bit
0x800504: beqs 0x800560 ; error (TRACK0 should be 1)
0x800506: bras 0x80056a ; good - at Track 0
; *********************************************************
; Entry point for Hard Disk 0
; The SDH value of 0x20 = 512 byte sectors, drive 0, head 0
; only call is from 800416 above
; *********************************************************
0x800508: clrw 0xc60026:l ; HD reset off
0x80050e: jsr 0x800472:l ; setup 8259 (all disabled)
0x800514: tstl d5
0x800516: beqs 0x80056a
0x800518: movw #0x20,0xc60002:l ; write precomp cyl
0x800520: movw #0x20,0xc6000c:l ; SDH (1/4)
0x800528: bras 0x800542
; *********************************************************
; Entry point for Hard Disk 1
; The SDH value of 0x28 = 512 byte sectors, drive 1, head 0
; only call is from 800420 above
; *********************************************************
0x80052a: clrw 0xc60026:l ; HD reset off
0x800530: jsr 0x800472:l ; setup 8259 (all disabled)
0x800536: tstl d5
0x800538: beqs 0x80056a
0x80053a: movw #0x28,0xc6000c:l ; SDH (2/4)
; common code for both Hard Disks
0x800542: movb d0,a0@(0x21) ; 0 = HD0, 1 - HD1
0x800546: movw #0x10,0xc6000e:l ; HD restore cmd
0x80054e: movb #0,a0@(0x20) ; HD = 0, FD = 1
0x800554: jsr 0x800a1a:l ; wait for completion
0x80055a: btst #0,d0 ; HD error bit
0x80055e: beqs 0x80056a ; OK if zero
0x800560: movl #4,d7 ; set error status
0x800566: bra 0x800432 ; return
; common code for everyone (FD and HD)
; recalibrate ends up here if everything went well
0x80056a: movw #4,a0@(0)
0x800570: movw #4,a0@(2)
0x800576: movw #4,a0@(4)
0x80057c: movw #4,a0@(6)
0x800582: movw #1,a0@(8) ; never used
0x800588: movw #1,a0@(0xa)
0x80058e: movb #1,a0@(0xe) ; flags (density...)
0x800594: clrw a0@(0xc)
0x800598: cmpb #1,a0@(0x20) ; 1 = FD
0x80059e: bnes 0x8005a6
0x8005a0: clrb a0@(0xf) ; 0 for a floppy
0x8005a4: bras 0x8005ac
0x8005a6: movb #2,a0@(0xf) ; 2 for a hard disk
0x8005ac: jsr 0x800350:l ; read "superblock"
0x8005b2: tstl d7 ; did it work ?
0x8005b4: bne 0x800432 ; NO
0x8005b8: movl 0x2004:l,a1
0x8005be: addl #0xe,a1
0x8005c4: movw a1@+,a0@(8) ; ( 0x300e ) never used
0x8005c8: movw a1@+,a0@(0xa) ; ( 0x3010 )
0x8005cc: movw a1@+,d0 ; ( 0x3012 )
0x8005ce: movw d0,d1
0x8005d0: movw d0,a0@(2) ; sectors/track
0x8005d4: andw #-2,d0 ; force even
0x8005d8: movw d0,a0@(0) ; sectors/track - even
0x8005dc: movw a1@+,d2 ; ( 0x3014 )
0x8005de: movw d2,a0@(6) ; sectors/cyl
0x8005e2: andl #0xffff,d2
0x8005e8: divu d1,d2
0x8005ea: mulu d0,d2
0x8005ec: movw d2,a0@(4) ; sectors/cyl - fiddled
0x8005f0: movb a1@+,a0@(0xe) ; ( 0x3016 ) flags (density...)
0x8005f4: movb a1@+,a0@(0xf) ; ( 0x3017 ) HD seek/restore
0x8005f8: movw a1@+,a0@(0x10) ; ( 0x3018 ) never used
0x8005fc: movl 0x2004:l,a1
0x800602: addl #0x60,a1
0x800608: movl a1@+,d4 ; ( 0x3060 )
0x80060a: movl a1@,d2 ; ( 0x3064 ) ??? long ???
0x80060c: beqs 0x800680
; note above that the test on 0x3064 is done long, but this surely was meant
; to be word. Look at the notes before the 800398 routine, this will work
; since the entry at 0x3066 is the pointer the the dump area, and will most
; likely have the upper 2 bytes zero (unless the dump area is at the end of
; a really big hard disk). Notice that this "entry" is only tested, never used.
; special code follows - should only find this stuff if this is a hard disk
; the entry on floppys should always be zero.
0x80060e: lsll #1,d4 ; start sector
0x800610: movl #2,d5 ; this many 512 byte sectors
0x800616: movl 0x2004:l,d3 ; read to this address
0x80061c: clrl d7
0x80061e: jsr 0x8006a2:l ; Read Em!
0x800624: tstl d7 ; Did it work
0x800626: bnes 0x800676 ; no - trouble
0x800628: movl 0x2004:l,a1 ; address of buffer
0x80062e: jsr 0x8003d4:l ; calculate checksum
0x800634: cmpl #-1,d5 ; better be (-1)
0x80063a: bnes 0x800676 ; no - trouble
0x80063c: movl #0x7f,d4 ; no more than this many
0x800642: movl 0x2004:l,a1 ; start here
0x800648: addl #8,a1 ; skip the first 8 bytes
0x80064e: lea a0@(0x26),a2 ; use this as a buffer
0x800652: movw a1@+,d3 ; Loop
0x800654: movw d3,a2@+ ; copy 2 bytes
0x800656: clrl d0
0x800658: movw a1@+,d0 ; or this on....
0x80065a: orw d0,d3 ; just to check for zero.
0x80065c: tstw d3 ; if it is.....
0x80065e: beqs 0x800680 ; Exit loop.
0x800660: divu a0@(2),d0 ; divide by sectors/track
0x800664: movw d0,a2@+
0x800666: swap d0
0x800668: movw d0,a2@+
0x80066a: movw a1@+,a2@+
0x80066c: addql #2,a1
0x80066e: addqw #1,a0@(0xc) ; count these
0x800672: subql #1,d4
0x800674: bgts 0x800652 ; get more
0x800676: movl #5,d7 ; return with d7=5
0x80067c: bra 0x800432
0x800680: movl #0,d7 ; return with d7=0
0x800686: bra 0x800432
; ************************************************
; ** General IO routines -- Write/Format/Read ***
; **
; ** d3 = memory address for i/o
; ** d4 = disk address (in # of 512 byte sectors)
; ** d5 = # of 512 byte sectors to move
; ** d6 = device (2=FD, 1=HD1, 0=HD0)
; ** d7 = 0 or 1
; ************************************************
;
; Write - Called from 800274 (for memory dump)
; also External entry
0x80068a: moveml d0-d6/a0-a7,sp@-
0x80068e: movl #1,d2 ; 1 = Write
0x800694: bras 0x8006ac
; Format - External calls only
0x800696: moveml d0-d6/a0-a7,sp@-
0x80069a: movl #2,d2 ; 2 = Format
0x8006a0: bras 0x8006ac
; Read - Called from 800324 (to read loader),
; Called from 800364 (to read "superblock" for loader/dump pointers),
; Called from 80061e (to read "superblock" for disk params)
; also External entry
0x8006a2: moveml d0-d6/a0-a7,sp@-
0x8006a6: movl #0,d2 ; 0 = Read
; common code for the 3 entry points above
0x8006ac: movl d7,d0 ; copy d7 to d0 (to save it)
0x8006ae: jsr 0x800438:l ; get a0 pointer (based on d6)
0x8006b4: tstl d7 ; only non-zero if d6 invalid
0x8006b6: bne 0x80042c ; invalid d6 (return w/d7=3)
0x8006ba: clrw 0xc60030:l ; disable disk DMA
0x8006c0: clrw 0xc60036:l ; reset disk BIU
0x8006c6: movb d0,a0@(0x25) ; low byte of d7 (0 or 1)
0x8006ca: movb d2,a0@(0x24) ; 0=Read, 1=Write, 2=Format
0x8006ce: movw #0xa,a0@(0x22) ; 10 retries
0x8006d4: lsrl #1,d3 ; convert to word address
0x8006d6: movl d3,a0@(0x12) ; save word address
0x8006da: movw a0@(4),d0
0x8006de: movw a0@(0),d3
0x8006e2: tstb a0@(0x25)
0x8006e6: beqs 0x8006f0
0x8006e8: movw a0@(6),d0
0x8006ec: movw a0@(2),d3
; now: d0 = sectors/cyl
; d3 = sectors/track
0x8006f0: divu d0,d4
0x8006f2: movw d4,a0@(0x16) ; desired cylinder
0x8006f6: swap d4 ; get remainder
0x8006f8: andl #0xffff,d4
0x8006fe: divu d3,d4
0x800700: movw d4,a0@(0x18) ; desired head
0x800704: swap d4 ; get remainder
0x800706: movw d4,a0@(0x1a) ; desired sector
0x80070a: movw d5,a0@(0x1c) ; # of blocks (512 byte)
0x80070e: movw d5,a0@(0x1e) ; # of blocks (512 byte)
; entered from 8008c2, 800a16, 800c24
0x800712: tstw a0@(0x1c) ; need any more
0x800716: ble 0x800680 ; NO - all done !!!!
0x80071a: cmpb #1,a0@(0x20) ; 1 = FD
0x800720: bnes 0x800736
0x800722: cmpb #2,a0@(0x24) ; 2 = Format (Floppy)
0x800728: beq 0x8007d6
0x80072c: movw #1,a0@(0x1e) ; Floppy R/W 1 sector at a time
0x800732: bra 0x8007d6
0x800736: cmpb #2,a0@(0x24) ; 2 = Format (Hard disk)
0x80073c: bge 0x8007d6 ; HD format bypasses
; Hard Disk read/write tangles with what follows...
0x800740: lea a0@(0x26),a1 ; use this as a buffer
0x800744: movw a0@(0xc),d0 ; count of entries
0x800748: andl #0xffff,d0
0x80074e: movw a0@(0x1a),d1 ; sector number
0x800752: andl #0xffff,d1
0x800758: addw a0@(0x1c),d1 ; sector count
0x80075c: bras 0x800764
0x80075e: addql #2,a1
0x800760: addql #2,a1
0x800762: addql #2,a1
0x800764: subql #1,d0
0x800766: blts 0x8007ac
0x800768: movw a1@+,d2
0x80076a: cmpw a0@(0x16),d2 ; cylinder
0x80076e: bnes 0x80075e
0x800770: movw a1@+,d2
0x800772: cmpw a0@(0x18),d2 ; head
0x800776: bnes 0x800760
0x800778: movw a1@+,d2
0x80077a: cmpw a0@(0x1a),d2 ; sector
0x80077e: blts 0x800762
0x800780: cmpw d1,d2
0x800782: bges 0x800762
0x800784: subw a0@(0x1a),d2 ; sector
0x800788: bnes 0x8007d2
0x80078a: movw #1,a0@(0x1e) ; sector count
0x800790: clrl d3
0x800792: movw a1@,d3
0x800794: divu a0@(0xa),d3
0x800798: clrl d4
0x80079a: movw d3,d4
0x80079c: swap d3
0x80079e: andl #0xffff,d3
0x8007a4: clrl d5
0x8007a6: movw a0@(0),d5
0x8007aa: bras 0x8007e8
0x8007ac: movw a0@(0x1a),d0 ; sector number
0x8007b0: andl #0xffff,d0
0x8007b6: addw a0@(0x1c),d0 ; sector count
0x8007ba: movw a0@(0),d5 ; set d5 to sectors/track
0x8007be: tstb a0@(0x25)
0x8007c2: beqs 0x8007c8
0x8007c4: movw a0@(2),d5
0x8007c8: cmpw d5,d0
0x8007ca: bles 0x8007d6
0x8007cc: movw d5,d2
0x8007ce: subw a0@(0x1a),d2 ; sector number
0x8007d2: movw d2,a0@(0x1e) ; sector count
0x8007d6: clrl d5
0x8007d8: clrl d4
0x8007da: clrl d3
0x8007dc: movw a0@(0x16),d4 ; cylinder
0x8007e0: movw a0@(0x18),d3 ; head
0x8007e4: movw a0@(0x1a),d5 ; sector
0x8007e8: movl a0@(0x12),d1 ; word address
0x8007ec: movw a0@(0x1e),d0 ; sector count
0x8007f0: andl #0xffff,d0
0x8007f6: cmpb #2,a0@(0x24) ; 2 = Format
0x8007fc: bnes 0x80080c
0x8007fe: lsrl #1,d0 ; Formatting - adjust count
0x800800: cmpb #0,a0@(0x20) ; 0 = HD
0x800806: bnes 0x80080e
0x800808: addql #2,d1 ; HD format skips 2 items
0x80080a: bras 0x80080e
0x80080c: lsll #8,d0 ; convert to word count
0x80080e: negl d0 ; fix for DMA count
; set up for disk DMA, both floppy and hard disk share the same channel
0x800810: movw d0,0xc80000:l ; DMA 16 bit word count
0x800816: movw d1,0xc80002:l ; DMA low 16 addr bits
0x80081c: swap d1 ; 16 bit <= =>
0x80081e: cmpb #0,a0@(0x24) ; 0=Read
0x800824: bnes 0x80082e ; 1=Write 2 = Format
0x800826: movw d1,0xc80008:l ; DMA high addr - Read
0x80082c: bras 0x800834
0x80082e: movw d1,0xc80006:l ; DMA high addr - Write
0x800834: cmpb #1,a0@(0x20) ; 1 = FD
0x80083a: beq 0x800b3a ; go to FD routine
0x80083e: clrw 0xc6002c:l ; HD reset off
0x800844: jsr 0x8008ee:l ; setup HD transfer
0x80084a: cmpb #0,a0@(0x24) ; 0 = Read
0x800850: bnes 0x80085c
0x800852: movw #0x2c,0xc6000e:l ; HD read multi-sectors
0x80085a: bras 0x800876
0x80085c: cmpb #2,a0@(0x24) ; 2 = Format
0x800862: bnes 0x80086e ; 1 = Write
0x800864: movw #0x50,0xc6000e:l ; HD write format
0x80086c: bras 0x800876
0x80086e: movw #0x34,0xc6000e:l ; HD write multi-sectors
0x800876: jsr 0x800a1a:l ; wait for completion
0x80087c: movl d0,d7 ; check status
0x80087e: andl #0xa3,d7
0x800884: beq 0x8009c8 ; good!
; here on hard disk IO error
0x800888: tstb a0@(0x25) ; are we allowing retries
0x80088c: bnes 0x8008c6 ; No
0x80088e: cmpw #5,a0@(0x22) ; retry count ( 10 initially )
0x800894: bnes 0x8008b6
0x800896: clrw 0xc60026:l ; HD reset off
0x80089c: clrl d3
0x80089e: clrl d4
0x8008a0: clrl d5
0x8008a2: jsr 0x80097a:l
0x8008a8: jsr 0x8009a4:l
0x8008ae: btst #0,d0 ; any error in HD status
0x8008b2: bne 0x800560 ; trouble
0x8008b6: addql #1,0x200e:l ; count the retries
0x8008bc: subw #1,a0@(0x22) ; --retry
0x8008c2: bgt 0x800712 ; Do it again
; too many retries - return with error status
; FD and HD use this, but some bits only make sense for HD
0x8008c6: movl #6,d7 ; start building a status
0x8008cc: addb a0@(0x24),d7 ; 0=Read, 1=Write, 2=Format
0x8008d0: andl #0xff,d0 ; mask completion status
0x8008d6: swap d0 ; swap 16 bit halves
0x8008d8: orl d0,d7 ; add that on
0x8008da: movw 0x200c:l,d0 ; error flags from WD1010
0x8008e0: andl #0xff,d0 ; just a byte
0x8008e6: rorl #8,d0 ; move left 8 bits
0x8008e8: orl d0,d7 ; and tack it on
0x8008ea: bra 0x800432 ; return with fancy code in d7
; called from 800844, 80097a, 8009aa
; HD1 needs write precomp set, HD0 doesn't (but will inherit HD1 settings)
0x8008ee: cmpb #1,a0@(0x21) ; 0 = HD0, 1 = HD1
0x8008f4: beqs 0x8008fe
0x8008f6: movw #0x20,0xc60002:l ; HD Write precomp cyl
0x8008fe: movw a0@(0x1e),d0
0x800902: cmpb #2,a0@(0x24) ; 2 = format
0x800908: bnes 0x800914
0x80090a: movl a0@(0x12),d0 ; Formatting
0x80090e: lsll #1,d0
0x800910: movl d0,a1
0x800912: movw a1@+,d0
0x800914: movw d0,0xc60004:l ; HD sector count
0x80091a: clrl d1
0x80091c: movb a0@(0xe),d0 ; density flags (and this)
0x800920: andl #4,d0
0x800926: beqs 0x80093a
0x800928: bset #5,d1 ; tweak cylinder number
0x80092c: cmpw #7,d3 ; tweak sector number
0x800930: bles 0x80093a
0x800932: bset #6,d1 ; tweak cylinder number
0x800936: addw #0x20,d5 ; tweak sector number
0x80093a: cmpb #2,a0@(0x24) ; 2 = Format
0x800940: bnes 0x800944
0x800942: movw a1@,d5
0x800944: movw d5,0xc60006:l ; HD sector number
0x80094a: movw d4,0xc60008:l ; HD cyl number (low)
0x800950: lsrl #8,d4
0x800952: andl #0xff,d4
0x800958: orw d4,d1
0x80095a: movw d1,0xc6000a:l ; HD cyl number (high)
0x800960: andl #7,d3 ; 3 bits
0x800966: movl d6,d0
0x800968: lsll #3,d0 ; drive (0 or 1)
0x80096a: orl d0,d3
0x80096c: orl #0x20,d3 ; 512 byte sectors always
0x800972: movw d3,0xc6000c:l ; SDH (3/4)
0x800978: rts
0x80097a: jsr 0x8008ee:l
0x800980: clrl d0
0x800982: movb a0@(0xf),d0
0x800986: addw #0x70,d0 ; HD seek command
0x80098a: movw d0,0xc6000e:l
0x800990: jsr 0x800a1a:l ; wait for completion
0x800996: movw 0xc6000e:l,d0 ; HD status
0x80099c: btst #1,d0 ; Cmd in Progress
0x8009a0: bnes 0x800996 ; Poll till done
0x8009a2: rts
0x8009a4: clrl d3
0x8009a6: clrl d4
0x8009a8: clrl d5
0x8009aa: jsr 0x8008ee:l
0x8009b0: clrl d0
0x8009b2: movb a0@(0xf),d0
0x8009b6: addw #0x10,d0 ; HD restore command
0x8009ba: movw d0,0xc6000e:l
0x8009c0: jsr 0x800a1a:l ; wait for completion
0x8009c6: rts
; successful hard disk AND floppy disk IO comes here:
; from 800bda (floppy) and 800884 (hard)
0x8009c8: movw a0@(0x1e),d0
0x8009cc: subw d0,a0@(0x1c)
0x8009d0: movw d0,d1
0x8009d2: addw a0@(0x1a),d1
0x8009d6: clrl d2
0x8009d8: movw a0@(0),d3
0x8009dc: tstb a0@(0x25)
0x8009e0: beqs 0x8009e6
0x8009e2: movw a0@(2),d3
0x8009e6: cmpw d3,d1
0x8009e8: blts 0x8009f2
0x8009ea: movl #1,d2
0x8009f0: clrl d1
0x8009f2: movw d1,a0@(0x1a)
0x8009f6: addw a0@(0x18),d2
0x8009fa: cmpw a0@(0xa),d2
0x8009fe: blts 0x800a06
0x800a00: clrl d2
0x800a02: addqw #1,a0@(0x16)
0x800a06: movw d2,a0@(0x18)
0x800a0a: lsll #8,d0
0x800a0c: addl d0,a0@(0x12)
0x800a10: movw a0@(0x1c),a0@(0x1e)
0x800a16: bra 0x800712
; ************************************************
; ** Routine to wait for HD command completion. **
; ************************************************
;
; Activate 8259 for HD interrupts
; 0x9f = OCW1 -- Unmask level 6 and 5 (Disk error, and HD EOXfer)
; 0x0e = OCW3 -- Poll IR register on next read
0x800a1a: movw #0x9f,0xc90002:l
0x800a22: movl #0x927c0,d1 ; 600,000 decimal (timeout)
0x800a28: movw #0xe,0xc90000:l
0x800a30: subql #1,d1
0x800a32: bnes 0x800a50
0x800a34: movw 0xc6000e:l,d0 ; timeout
0x800a3a: movw #-0x1111,0x200a:l ; set status
0x800a42: clrw 0xc60030:l ; disable disk DMA
0x800a48: clrw 0xc60036:l ; reset disk BIU
0x800a4e: bras 0x800a96
; read 8259 IR register, 0x85 = interrupt at level 05 (overflow or underrun)
; 0x86 = interrupt at level 06 (HD end of Xfer)
0x800a50: movw 0xc90000:l,d0
0x800a56: cmpb #0x85,d0
0x800a5a: bnes 0x800a76
; here with overflow/underrun
0x800a5c: clrw 0xc60024:l ; HD reset on
0x800a62: rorl #8,d1
0x800a64: roll #8,d1
0x800a66: clrw 0xc60026:l
0x800a6c: movw #-0x1101,0x200a:l ; set status (home-made)
0x800a74: bras 0x800a42
0x800a76: cmpb #0x86,d0
0x800a7a: bnes 0x800a28 ; keep on going
; here with successful End of transfer
0x800a7c: clrw 0xc60030:l ; disable disk DMA
0x800a82: movw 0xc6000e:l,0x200a:l ; save status (WD1010)
0x800a8c: movw 0xc60002:l,0x200c:l ; save err flags (1010)
; Reset 8259
; 0xff = OCW1 -- Mask all interrupt levels
; HD_SDH = 0x18 sets 256 byte sectors, drive 4, head 0 (Impossible drive)
0x800a96: movw #0xff,0xc90002:l
0x800a9e: clrw 0xc60036:l ; reset disk BIU
0x800aa4: movw #0x18,0xc6000c:l ; SDH (4/4)
; The DMA word count here is stored, never referenced anywhere
0x800aac: movw 0xc80000:l,0x2008:l ; DMA word count (disk)
0x800ab6: movw 0x200a:l,d0 ; fetch status
0x800abc: rts
; ************************************************
; ** Routine to wait for FD command completion. **
; ************************************************
;
; Activate 8259 for FD interrupts
; 0x7f = OCW1 -- Unmask level 7 (FD EOXfer)
; 0x0e = OCW3 -- Poll IR register on next read
0x800abe: movw #0x7f,0xc90002:l
0x800ac6: movl #0x61a80,d1 ; 400,000 decimal (timeout)
0x800acc: movw #0xe,0xc90000:l
0x800ad4: subql #1,d1
0x800ad6: bnes 0x800aee
0x800ad8: movw #-0x1107,0x200a:l ; timed out! set status
0x800ae0: clrw 0xc60030:l ; disable disk DMA
0x800ae6: clrw 0xc60036:l ; reset disk BIU
0x800aec: bras 0x800a96 ; remask interrupts, return
; read 8259 IR register, 0x87 = interrupt at level 07
0x800aee: movw 0xc90000:l,d0 ; poll the 8259
0x800af4: cmpb #0x87,d0 ; are we done?
0x800af8: bnes 0x800acc ; no, poll some more
0x800afa: clrw 0xc60030:l ; Done! disable disk DMA
0x800b00: movw 0xc60010:l,0x200a:l ; save status (2797)
0x800b0a: bras 0x800a96 ; remask interrupts, return
; ************************************************
; ** Routine to set floppy density
; ** a0@(0x16) is current cyliner number
; ** a0@(0xe) are density flags as follows:
; ------00 -- single density
; ------01 -- double density
; ------1x and cyl==0 -- single density
; ------1x and cyl!=0 -- double density
; ************************************************
0x800b0c: movb a0@(0xe),d0 ; check flags
0x800b10: andl #2,d0 ; cylinder number stuff ?
0x800b16: beqs 0x800b26 ; NO
0x800b18: tstw a0@(0x16) ; cyliner zero
0x800b1c: bnes 0x800b32 ; NO
0x800b1e: clrw 0xc60032:l ; set single density
0x800b24: rts
0x800b26: movb a0@(0xe),d0 ; check flags
0x800b2a: andl #1,d0 ; always double density ?
0x800b30: beqs 0x800b1e ; NO - then always single
0x800b32: clrw 0xc60034:l ; set double density
0x800b38: rts
; ************************************************
; ** common routine for floppy disk IO **********
; ************************************************
;
; first thing is to seek to the correct track
0x800b3a: movw d4,0xc60016:l ; write track # to data reg.
0x800b40: cmpb 0xc60013:l,d4 ; compare with track reg.
0x800b46: beqs 0x800b90 ; same - no need to seek
0x800b48: jsr 0x800b0c:l ; set density
0x800b4e: cmpb #2,a0@(0x24) ; 2 = Format
0x800b54: bnes 0x800b60 ; not formatting
0x800b56: movw #0x10,0xc60010:l ; Formatting - just seek
0x800b5e: bras 0x800b68 ; otherwise:
0x800b60: movw #0x14,0xc60010:l ; seek with verify
0x800b68: jsr 0x800abe:l ; wait for command complete
0x800b6e: movl d0,d7 ; get status
0x800b70: andl #0x98,d7 ; Not Rdy | Seek Err | CRC
0x800b76: beqs 0x800b90 ; Good! none of these bits set
; FD seek error
0x800b78: tstb a0@(0x25) ; allowing retries
0x800b7c: bnes 0x800b8c ; No
0x800b7e: addql #1,0x200e:l ; count the retries
0x800b84: subw #1,a0@(0x22) ; --retry
0x800b8a: bgts 0x800b3a ; try again
0x800b8c: bra 0x8008c6 ; build error status, return
; Here after successful seek to desired track
; set up and start the desired command.
0x800b90: clrw 0xc6002e:l ; enable floppy DMA
0x800b96: addqw #1,d5 ; add 1 to sector number
0x800b98: movw d5,0xc60014:l ; write it to sector reg
0x800b9e: jsr 0x800b0c:l ; set density
0x800ba4: lslw #1,d3 ; side select bit
0x800ba6: cmpb #0,a0@(0x24) ; 0 = Read
0x800bac: bnes 0x800bb4
0x800bae: addw #0x88,d3 ; read single sector
0x800bb2: bras 0x800bc6
0x800bb4: cmpb #2,a0@(0x24) ; 2 = Format ( 1 = Write )
0x800bba: bnes 0x800bc2
0x800bbc: addw #0xf0,d3 ; format (write track)
0x800bc0: bras 0x800bc6
0x800bc2: addw #0xa8,d3 ; write single sector
0x800bc6: movw d3,0xc60010:l ; start the command !
0x800bcc: jsr 0x800abe:l ; wait for completion
0x800bd2: movl d0,d7 ; get status
0x800bd4: andl #0xdc,d7 ; mask for error bit (2797FDC)
0x800bda: beq 0x8009c8 ; good! none of these set
; Floppy disk IO error
0x800bde: tstb a0@(0x25) ; allowing retries
0x800be2: bnes 0x800c28 ; No
0x800be4: cmpw #5,a0@(0x22) ; check retry count
0x800bea: bnes 0x800c18 ; do it again
0x800bec: clrw 0xc60022:l ; FD reset off
0x800bf2: jsr 0x800b0c:l ; set density
0x800bf8: movw #0,0xc60010:l ; restore command
;; Some funny business here, I believe the ROM just lost a bit --
;; The following 3 words:
;; 0x800c00: 4eb1 0080 0abe
;; Disassemble as this junk: (and grab a fourth word)
;; 0x800c00: jsr a1@(-0x80,d0:w) ; (8 bytes, nonsense)
;; If we set just one bit:
;; 0x800c00: 4eb9 0080 0abe
;; This disassembles as:
;; 0x800c00: jsr 0x800abe:l
;; And the following instruction as:
;; 0x800c06: 4279 00c6 0012
;; 0x800c06: clrw 0xc60012:l
;; Which makes sense, so I reproduce this code below:
0x800c00: jsr 0x800abe:l ; wait for command completion
0x800c06: clrw 0xc60012:l ; write 0 to track register
0x800c0c: movl d0,d7 ; look at status
0x800c0e: andl #4,d7 ; Expect 1 here (Track 0)
0x800c14: beq 0x800560 ; trouble
0x800c18: addql #1,0x200e:l ; count the retries
0x800c1e: subw #1,a0@(0x22) ; --retry
0x800c24: bgt 0x800712 ; do it again
0x800c28: bra 0x8008c6 ; build error status, return
/* The End */