Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

443 lines
10 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

title 'SBC86/12 w/ SBC204 Bootstrap EPROM'
;
; ROM bootstrap for CP/M-86 on an iSBC86/12
; with the
; Intel SBC 204 Floppy Disk Controller
;
; Copyright (C) 1980,1981
; Digital Research, Inc.
; Box 579, Pacific Grove
; California, 93950
;
;********************************************
;* This is the BOOT ROM which is initiated *
;* by a system reset. First, the ROM moves *
;* a copy of its data area to RAM at loca- *
;* tion 00000H, then initializes the segment*
;* registers and the stack pointer. The *
;* various peripheral interface chips on the*
;* SBC 86/12 are initialized. The 8251 *
;* serial interface is configured for a 9600*
;* baud asynchronous terminal, and the in- *
;* terrupt controller is setup for inter- *
;* rupts 10H-17H (vectors at 00040H-0005FH) *
;* and edge-triggered auto-EOI (end of in- *
;* terrupt) mode with all interrupt levels *
;* masked-off. Next, the SBC 204 Diskette *
;* controller is initialized, and track 1 *
;* sector 1 is read to determine the target *
;* paragraph address for LOADER. Finally, *
;* the LOADER on track 0 sectors 2-26 and *
;* track 1 sectors 1-26 is read into the *
;* target address. Control then transfers *
;* to LOADER. This program resides in two *
;* 2716 EPROM's (2K each) at location *
;* 0FF000H on the SBC 86/12 CPU board. ROM *
;* 0 contains the even memory locations, and*
;* ROM 1 contains the odd addresses. BOOT *
;* ROM uses RAM between 00000H and 000FFH *
;* (absolute) for a scratch area, along with*
;* the sector 1 buffer. *
;********************************************
true equ 0ffh
false equ not true
;
debug equ true
;debug = true indicates bootstrap is in same roms
;with SBC 957 "Execution Vehicle" monitor
;at FE00:0 instead of FF00:0
;
cr equ 13
lf equ 10
;
; disk ports and commands
;
base204 equ 0a0h
fdccom equ base204+0
fdcstat equ base204+0
fdcparm equ base204+1
fdcrslt equ base204+1
fdcrst equ base204+2
dmacadr equ base204+4
dmaccont equ base204+5
dmacscan equ base204+6
dmacsadr equ base204+7
dmacmode equ base204+8
dmacstat equ base204+8
fdcsel equ base204+9
fdcsegment equ base204+10
reset204 equ base204+15
;
;actual console baud rate
baud_rate equ 9600
;value for 8253 baud counter
baud equ 768/(baud_rate/100)
;
csts equ 0DAh ;i8251 status port
cdata equ 0D8h ; " data port
;
tch0 equ 0D0h ;8253 PIC channel 0 port
tch1 equ tch0+2 ;ch 1 port
tch2 equ tch0+4 ;ch 2 port
tcmd equ tch0+6 ;8253 command port
;
icp1 equ 0C0h ;8259a port 0
icp2 equ 0C2h ;8259a port 1
;
;
IF NOT DEBUG
ROMSEG EQU 0FF00H ;normal
ENDIF
;
IF DEBUG ;share prom with SBC 957
ROMSEG EQU 0FE00H
ENDIF
;
;
; This long jump prom'd in by hand
; cseg 0ffffh ;reset goes to here (ffff0h)
; JMPF BOTTOM ;boot is at bottom of PROM
; EA 00 00 00 FF ;cs = bottom of prom (ff000h)
; ip = 0
; EVEN PROM ODD PROM
; 7F8 - EA 7F8 - 00
; 7F9 - 00 7F9 - 00
; 7FA - FF ;this is not done if special = true
;
cseg romseg
;
;First, move our data area into RAM at 0000:0200
;
mov ax,cs
mov ds,ax ;point DS to CS for source
mov SI,drombegin ;start of data
mov DI,offset ram_start ;offset of destination
mov ax,0
mov es,ax ;destination segment is 0000
mov CX,data_length ;how much to move in bytes
rep movs al,al ;move out of eprom a byte at a time
;
mov ax,0
mov ds,ax ;data segment now in RAM
mov ss,ax
mov sp,stack_offset ;Initialize stack segment/pointer
cld ;clear the direction flag
;
IF NOT DEBUG
;
;Now, initialize the console USART and baud rate
;
mov al,0Eh
out csts,al ;give 8251 dummy mode
mov al,40h
out csts,al ;reset 8251 to accept mode
mov al,4Eh
out csts,al ;normal 8 bit asynch mode, * 16
mov al,37h
out csts,al ;enable Tx & Rx
mov al,0B6h
out tcmd,al ;8253 ch.2 square wave mode
mov ax,baud
out tch2,al ;low of the baud rate
mov al,ah
out tch2,al ;high of the baud rate
;
ENDIF
;
;Setup the 8259 Programmable Interrupt Controller
;
mov al,13h
out icp1,al ;8259a ICW 1 8086 mode
mov al,10h
out icp2,al ;8259a ICW 2 vector @ 40-5F
mov al,1Fh
out icp2,al ;8259a ICW 4 auto EOI master
mov al,0FFh
out icp2,al ;8259a OCW 1 mask all levels off
;
;Reset and initialize the iSBC 204 Diskette Interface
;
restart: ;also come back here on fatal errors
out reset204,AL ;reset iSBC 204 logic and
mov AL,1
out fdcrst,AL ;give 8271 FDC
mov al,0
out fdcrst,AL ; a reset command
mov BX,offset specs1
CALL sendcom ;program
mov BX,offset specs2
CALL sendcom ; Shugart SA-800 drive
mov BX,offset specs3
call sendcom ; characteristics
homer: mov BX,offset home
CALL execute ;home drive 0
;
mov bx,sector1 ;offset for first sector DMA
mov ax,0
mov es,ax ;segment " " " "
call setup_dma
;
mov bx,offset read0
call execute ;get T0 S1
;
mov es,ABS
mov bx,0 ;get loader load address
call setup_dma ;setup DMA to read loader
;
mov bx,offset read1
call execute ;read track 0
mov bx,offset read2
call execute ;read track 1
;
mov leap_segment,ES
; setup far jump vector
mov leap_offset,0
;
; enter LOADER
jmpf dword ptr leap_offset
;
pmsg:
mov cl,[BX]
test cl,cl
jz return
call conout
inc BX
jmp pmsg
;
conout:
in al,csts
test al,1
jz conout
mov al,cl
out cdata,al
ret
;
conin:
in al,csts
test al,2
jz conin
in al,cdata
and al,7Fh
ret
;
;
;
execute: ;execute command string @ [BX]
;<BX> points to length,
;followed by Command byte
;followed by length-1 parameter bytes
;
mov lastcom,BX ;remember what it was
retry: ;retry if not ready drive
call sendcom ;execute the command
;now, let's see what type
;of status poll was necessary
;for that command type . . .
mov BX,lastcom ;point to command string
mov AL,1[BX] ;get command op code
and AL,3fh ;drop drive code bits
mov CX,0800h ;mask if it will be "int req"
cmp AL,2ch ;see if interrupt type
jb execpoll
mov CX,8080h ;else we use "not command busy"
and AL,0fh ;unless . . .
cmp AL,0ch ;there isn't
mov AL,0
ja return ;any result at all
;
execpoll: ;poll for bit in b, toggled with c
in AL,FDCSTAT
and AL,CH
xor AL,CL ! JZ execpoll
;
in AL,fdcrslt ;get result register
and AL,1eh ;look only at result type & code
jz return ;zero means it was a good operation
;
cmp al,10h
jne fatal ;if other than "Not Ready", stop
;
mov bx,offset rdstat
call sendcom ;perform read status command
rd_poll:
in al,fdc_stat
test al,80h ;wait for command not busy
jnz rd_poll
mov bx,last_com ;recover last attempted command
jmp retry ;and try it over again
;
fatal: ; fatal error
mov ah,0
mov bx,ax ;make 16 bits
mov bx,errtbl[BX]
; print appropriate error message
call pmsg
call conin ;wait for key strike
pop ax ;discard unused item
jmp restart ;then start all over
;
return:
RET ;return from EXECUTE
;
setupdma:
mov AL,04h
out dmacmode,AL ;enable dmac
mov al,0
out dmaccont,AL ;set first (dummy) byte to
mov AL,40h
out dmaccont,AL ;force read data mode
mov AX,ES
out fdcsegment,AL
mov AL,AH
out fdcsegment,AL
mov AX,BX
out dmacadr,AL
mov AL,AH
out dmacadr,AL
RET
;
;
;
sendcom: ;routine to send a command string to SBC204
in AL,fdcstat
and AL,80h
jnz sendcom ;insure command not busy
mov CL,[BX] ;get count
inc BX
mov al,[BX] ;point to and fetch command byte
out fdccom,AL ;send command
parmloop:
dec CL
jz return ;see if any (more) parameters
inc BX ;point to next parameter
parmpoll:
in AL,fdcstat
and AL,20h
jnz parmpoll ;loop until parm not full
mov AL,[BX]
out fdcparm,AL ;output next parameter
jmp parmloop ;go see about another
;
;
; Image of data to be moved to RAM
;
drombegin equ offset $
;
clastcom dw 0000h ;last command
;
creadstring db 3 ;length
db 52h ;read function code for drive 0
db 0 ;track #
db 1 ;sector #
;
creadtrk0 db 4
db 53h ;read multiple
db 0 ;track 0
db 2 ;sectors 2
db 25 ;through 26
;
creadtrk1 db 4
db 53h
db 1 ;track 1
db 1 ;sectors 1
db 26 ;through 26
;
chome0 db 2,69h,0
crdstat0 db 1,6ch
cspecs1 db 5,35h,0dh
db 08h,08h,0e9h
cspecs2 db 5,35h,10h
db 255,255,255
cspecs3 db 5,35h,18h
db 255,255,255
;
cerrtbl dw offset er0
dw offset er1
dw offset er2
dw offset er3
dw offset er4
dw offset er5
dw offset er6
dw offset er7
dw offset er8
dw offset er9
dw offset erA
dw offset erB
dw offset erC
dw offset erD
dw offset erE
dw offset erF
;
Cer0 db cr,lf,'Null Error ??',0
Cer1 equ cer0
Cer2 equ cer0
Cer3 equ cer0
Cer4 db cr,lf,'Clock Error',0
Cer5 db cr,lf,'Late DMA',0
Cer6 db cr,lf,'ID CRC Error',0
Cer7 db cr,lf,'Data CRC Error',0
Cer8 db cr,lf,'Drive Not Ready',0
Cer9 db cr,lf,'Write Protect',0
CerA db cr,lf,'Trk 00 Not Found',0
CerB db cr,lf,'Write Fault',0
CerC db cr,lf,'Sector Not Found',0
CerD equ cer0
CerE equ cer0
CerF equ cer0
;
dromend equ offset $
;
data_length equ dromend-drombegin
;
; reserve space in RAM for data area
; (no hex records generated here)
;
dseg 0
org 0200h
;
ram_start equ $
lastcom rw 1 ;last command
read0 rb 4 ;read track 0 sector 1
read1 rb 5 ;read T0 S2-26
read2 rb 5 ;read T1 S1-26
home rb 3 ;home drive 0
rdstat rb 2 ;read status
specs1 rb 6
specs2 rb 6
specs3 rb 6
errtbl rw 16
er0 rb length cer0 ;16
er1 equ er0
er2 equ er0
er3 equ er0
er4 rb length cer4 ;14
er5 rb length cer5 ;11
er6 rb length cer6 ;15
er7 rb length cer7 ;17
er8 rb length cer8 ;18
er9 rb length cer9 ;16
erA rb length cerA ;19
erB rb length cerB ;14
erC rb length cerC ;19
erD equ er0
erE equ er0
erF equ er0
;
leap_offset rw 1
leap_segment rw 1
;
;
rw 32 ;local stack
stack_offset equ offset $;stack from here down
;
; T0 S1 read in here
sector1 equ offset $
;
Ty rb 1
Len rw 1
Abs rw 1 ;ABS is all we care about
Min rw 1
Max rw 1
end