trs80m1: Model III loader
authorAlan Cox <alan@linux.intel.com>
Sat, 9 Jun 2018 15:55:47 +0000 (16:55 +0100)
committerAlan Cox <alan@linux.intel.com>
Sat, 9 Jun 2018 15:55:47 +0000 (16:55 +0100)
Kernel/platform-trs80m1/trs80load-m3.s [new file with mode: 0644]

diff --git a/Kernel/platform-trs80m1/trs80load-m3.s b/Kernel/platform-trs80m1/trs80load-m3.s
new file mode 100644 (file)
index 0000000..d2e5aa1
--- /dev/null
@@ -0,0 +1,165 @@
+.z80
+;
+;      TRS80 bootblock (256 bytes)
+;
+;      The model 3 bootblock is loaded at 0x4300 not 0x4200 as the model 1
+;      does. It's also double density and sector counts start at 1.
+;
+;      As we are going to blow away the existing setup and it's damned
+;      inconvenient have different load OS addresses by model we relocate
+;      ourselves down to 0x4200 and run from there
+;
+;
+;      We load from 0x4300-0xFFFF into common and bank 0, then switch
+;      to loading from 0x8000-0xFFFF in bank1. That takes 320 sectors
+;      at 10 sectors per track so 32 tracks of those available (which may
+;      only be 35). Track 0 holds the boot block.
+;
+;      We could optimize this once we have the layout better planned so we
+;      load less empty space. On the other hand we've only got 256 bytes
+;      of space to play in.
+;
+;      FIXME: Does this need to be a double density boot block and reader ?
+;      40 track SS/DD is known to work does 40 track SS/SD still work ?
+;
+;
+.area      BOOT        (ABS)
+.org       0x4200
+;
+;      The 1791 is I/O mapped but has halt logic to meeting timings.
+;
+FDCREG .equ    0xF0
+FDCTRK .equ    0xF1
+FDCSEC .equ    0xF2
+FDCDATA        .equ    0xF3
+
+FDCSEL .equ    0xF4                    ; and watch errata
+
+start:
+           ld hl,#0x4300
+           ld de,#0x4200
+           ld bc,#0x0100
+           ldir
+           jp go
+go:
+;          call 0x04C3                 ; 64 columns
+           ; Stack is at 407D
+           ; Loader message
+           ld de, #0x3C00
+           call prints
+           .ascii 'TRS80Load 0.2m3\0'
+           out (0x43),a                ; a is 0 on prints return
+           in a,(0x43)
+           or a
+           jr z, bank_ok
+           call printse
+           .ascii 'Supermem not found\0'
+bad:       jr bad
+
+bank_ok:
+           ld hl, #0x4300              ; page aligned buffer we read into
+lastsec:    ld a, #0                   ; self modifying to save space
+           inc a
+           ld (lastsec+1), a           ; track number... (start on 1)
+           out (FDCDATA),a             ; Desired track into data
+           ld a,#0x81
+           out (FDCSEL),a              ; MFM drive 1 no halt
+           ld a,#0x1B
+           out (FDCREG),a              ; seek, lowest step speed
+           ex (sp),hl
+           ex (sp),hl
+           ex (sp),hl
+           ex (sp),hl
+seekstat:
+           in a,(FDCREG)               ; Wait for busy to drop
+           rra
+           jr c,  seekstat
+           in a,(FDCREG)               ; Did it work ?
+           and #0x18
+           jr z, secmove
+           call printse
+           .ascii 'seek\0'
+bad2:      jr bad2
+
+secmove:    xor a
+           ld (nextsec+1), a
+nextsec:
+           ld a, #0            ; self modifying sector count
+           inc a
+           ld (nextsec+1), a
+           cp #19
+           jr z, lastsec
+           call floppy_read
+           push hl
+           ld l,h
+           ld h,#0x3D
+           inc (hl)
+           pop hl
+           jr nextsec
+;
+;      Assume the boot ROM left us on track 0 and motor on
+;
+floppy_read:
+           out (FDCSEC), a             ; sector please
+           ld a, #0x81                 ; drive 1 select, dd, side 0
+           out (FDCSEL), a             ; keep motor on
+           ld a, #0x80                 ; READ
+           out (FDCREG), a
+           ex (sp),hl                  ; 19: We need to wait 58 clocks
+           ex (sp),hl                  ; 38: not a lot more, no less
+           ld de,#0xC102               ; 48: D is used for the select
+                                       ; drive 1, double density, side 0.
+                                       ; wait
+           ld bc,#FDCDATA              ; 58: For the ini
+flopin:            in a, (FDCREG)
+           and e
+           jr z, flopin
+           ini                         ; First data byte
+           di
+           ld a,d                      ; drive/density etc
+flopinl:
+           out (FDCSEL),a              ; stall for byte
+           ini                         ; fetch
+           jp  nz, flopinl
+           ld a,h
+           or l
+           jr nz, flopstat             ; passed FFFF ?
+           ld h,#0x80                  ; go back to 8000 and change bank
+           in a,(0x43)
+           or a
+           jr nz, booted               ; already on second bank so boot
+           ld a,#1                     ; switch to bank 2
+            out (0x43),a
+flopstat:
+           in a, (FDCREG)
+           and #0x19
+           rra                         ; test bit 0
+           jr nc, flopdone
+           ld a,d
+           out (FDCSEL),a
+           jr flopstat
+flopdone:
+           or a                        ; safe even though we rotated right
+           ret z
+           call printse
+           .ascii 'Read\0'
+fail:      jr fail
+
+
+printse:
+          ld de, #0x3C40
+prints:
+          pop hl
+printsl:
+          ld a, (hl)
+          inc hl
+          or a
+          jr z, out
+          ld (de), a
+          inc de
+          jr printsl
+out:      jp (hl)
+
+booted:           call printse
+           .ascii 'Booting..\0'
+          jr 0x4300