Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 86/CONCURRENT/CCPM-86 3.1 SOURCE/D10/DSKBOOT.A86
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

361 lines
9.6 KiB
Plaintext
Raw 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 'Disk Boot for CompuPro DISK1'
;*******************************************************
; Last Modification: 10/14/83
;
; D i s k B O O T
;
; The following code is written onto track 0 sector
; 0 -3 of the disk. This routine is read into memory
; at location 0000:0100h by the CompuPro PROM. This
; routine then loads the system loader into memory.
;
; The format of the CompuPro Floppy Disk Boot sectors
; are as follows:
;
; Trk Sectors Description
; --- ------- -----------
; 0 1 thru 4 Disk Boot program (this routine)
;
; 5 Loader Group Header
; 6 thru 26 Loader Part 1
;
; 1 1 thru ? Loader Part 2 (remainder not on track 0)
; Number of sectors is determined by
; disk density and format.
;
; The following commands are used to generate DSKBOOT.CMD
; as an 8080 model routine
; RASM86 DSKBOOT
; LINK86 DSKBOOT.SYS = DSKBOOT [DATA[ORIGIN[0]]]
;
; The following commands are used to generate the
; boot tracks image in the file BOOTTRKS
; SID86
; #RDSKBOOT.SYS ;strips header and
; #WBOOT,180,37F ;default base page
; PIP BOOTTRKS = BOOT[O],CPMLDR.SYS[O]
;
;*******************************************************
N_TRK equ 26 ;sectors in Track 0
N_BOOT equ 4 ;sectors for Boot
; Assembly Constants
FDPORT equ 0C0H ;base port address for DISK1 Controller
FDC_S equ FDPORT ;8272 status register
FDC_D equ FDPORT+1 ;8272 data register
D1_DMA equ FDPORT+2 ;DISK1 DMA address (when write)
D1_INTS equ FDPORT+2 ;DISK1 status Register (when read)
DELCNT equ 5*1000 ;delay count for 5 MHz processor
RQM_DELAY equ 5 ;12us delay count for master status
; Intel 8272 controller function definitions
; Specify (00) command
F_SPEC equ 03 ;specify
F_DSTS equ 04 ;drive status
F_RDAT equ 06 ;read data
F_RECA equ 07 ;recalibrate
F_RSTS equ 08 ;read status
F_RID equ 0Ah ;read ID
F_SEEK equ 0Fh ;seek
SRT equ 16-8 ;shuggart 800s
HUT equ 240/16 ;head unload = 240 ms
HLT equ (35+1)/2 ;head load = 35 ms
ND equ 00 ;set DMA mode
cgroup group code,data ;force code and data into 8080 model
;-------------------------------------------------------
; Bootstrap load.
; Do not change any addresses from here to START:
; Entry CL= Board switches from CompuPro PROM (0 .. 3)
CSEG
org 0100H ;origin for 8080 model
nop! nop! nop ;these instructions have already
nop! nop! nop ; been prefetched from the
nop ; CompuPro boot PROM
; Start of Boot code.
; Save board option value.
; Load bios.
start:
;=====
cli
mov ax,cs
mov es,ax
mov ss,ax ;switch to local stack in base page
mov sp,offset stack ;area from 0080h down
xor bx,bx! mov ds,bx
mov opts,cl ;save DISK1 board options switch
mov ds,ax ;DS = CS, 8080 model
retry:
mov si,offset spec ;specify controller parameters
mov cl,LSPEC ;length of specify command
call send_command ;send command to 8272
;SI = offset of recal command
mov cl,LRECAL ;length of recal command
call send_command ;Recalibrate drive
end_rcal:
in al,D1_INTS ;interrupts are disabled, so we
or al,al! jns end_rcal ;poll for command completion
mov al,F_RSTS ;send sense interrupt status to 8272
out FDC_D,al ;required after recal command
mov cx,250 ;Leave lite on for 1/4 second
call delay
call wait_rqm ;wait for drive ready
in al,FDC_D ;get status 0 from 8272
sub al,020h ;remove seek end bit
mov cl,al
call wait_rqm ;wait for drive ready
in al,FDC_D ;get present cylinder number
or al,cl! jnz error ;error if not on track 0 after recal
mov ax,ds ;setup AX to segment address of CMD
add ax,offset header_buf/16 ; header buffer in base page for DMA
mov si,offset read_ghdr ;command to read loader group header
call disk_read ;read loader group header
jnz error ;if error
mov word ptr header_buf+1,0 ;setup offset for jump far to loader
mov ax,word ptr header_buf+3 ;AX = segment address of DMA
mov si,offset read ;command to read remainder of track 0
call disk_read ;read remainder of track 0
jz read_c1 ;if no errors
error: ; Disk error handler.
;-----
mov cx,2000 ;wait 2 seconds
call delay ; and start all over again
jmps retry
read_c1:
mov si,offset seek ;seek to cylinder 1
mov cl,LSEEK ;length of seek command
call send_command ;send command to 8272
end_seek:
in al,D1_INTS ;interrupts are disabled, so we
or al,al! jns end_seek ;poll for command completion
mov al,F_RSTS ;send sense interrupt status to 8272
out FDC_D,al ;required after seek command
call wait_rqm ;wait for drive ready
in al,FDC_D ;get status 0 from 8272
sub al,020h ;remove seek end bit
mov cl,al
call wait_rqm ;wait for drive ready
in al,FDC_D ;get present cylinder number
sub al,1 ;should be cylinder 1
or al,cl! jnz error ;if error then delay and try again
;determine density and sector
;size of cylinder 1
mov al,F_RID + 040h ;setup to try double density first
try_fm:
mov si,offset readid ;read id to determine density
mov [si],al ;set read command for desired density
mov cl,LREADID ;length of read id command
call execute ;execute command and read result bytes
mov al,status ;get status 0 of result bytes
or al,al! jz dens_ok
mov al,readid
xor al,040h ;toggle MFM flag
test al,040h! jnz error ;tried FM and MFM then error
jmps try_fm
dens_ok:
mov bl,status+6 ;get N field from result bytes
and bx,3! shl bx,1 ; to determine sector size
mov si,read1[bx] ;SI -> command to read side 0 of cyl 1
mov ax,word ptr header_buf+3
add ax,(128*(26-5))/16 ;AX = DMA segment address for cyl 1
call disk_read ;read cylinder 1
jnz error ;if error delay and try again
jmpf dword ptr header_buf+1 ;the group header has been setup
;to point to loader entry
wait_rqm: ;wait for drive ready
;--------
mov al,RQM_DELAY ;must delay 12us before polling
w_rqm1: ;FDC status to insure valid results
dec al ! jnz w_rqm1
w_rqm2:
in al,FDC_S ;get master status from 8272
or al,al! jns w_rqm2 ;if no master ready bit
ret
send_command: ; Send Function to Drive.
;------------
; Entry: SI -> command bytes
; CL = length of command.
; Exit: SI -> end of command + 1.
call wait_rqm ;wait for drive ready
lodsb ;load command byte
out FDC_D,al ;send to 8272 controller
dec cl! jnz send_command ;if more bytes
ret
disk_read: ; Disk Read.
;---------
; Entry: AX = segment address of DMA
; SI -> Command (9 bytes)
; Exit: SI -> End of Command + 1.
; Z flag set if successful read
push ax ;compute 24 bit DMA address
mov cl,4 ;for DISK1 DMA port
shr ax,cl ;AX = most significant 16 bits
xchg al,ah
out D1_DMA,al ;send highest address byte
xchg al,ah
out D1_DMA,al ;send middle address byte
pop ax
shl ax,cl
out D1_DMA,al ;send low address byte
mov cl,LREAD ;length of read command
execute:
call send_command ;send command to controller
wait_int_1:
in al,D1_INTS ;interrupts are disabled, so we
or al,al! jns wait_int_1 ;poll for command completion
mov di,offset status ;SI -> to buffer to save result bytes
mov cl,7 ;number of bytes to save
get_status:
call wait_rqm ;wait for drive ready
in al,FDC_D ;read result byte
stosb ;save in buffer
dec cl! jnz get_status ;wait until all done
mov ax,word ptr status ;get status 0 and 1
sub ax,8040h ;40h - zeros abnormal termination bit
;80h - zeros end of cylinder status bit
ret
delay: ;Delay process.
;-----
; Entry: CX = delay count (nominal milliseconds).
; Exit: AL modified
mov al,DELCNT/26
dely1:
inc cx! dec cx
dec al! jnz dely1 ;if not one millisecond
dec cx
mov al,ch
or al,cl! jnz delay ;if not requested time
ret
;-------------------------------------------------------
DSEG
opts equ byte ptr .0040h
stack equ word ptr .0080h
header_buf equ byte ptr .0080h
; Disk setup command strings.
spec db F_SPEC
db SRT shl 4 + HUT
db HLT shl 1 + ND
LSPEC equ offset $ - offset spec
recal db F_RECA
db 0
LRECAL equ offset $ - offset recal
; Read Loader Group Header.
read_ghdr db F_RDAT
db 0 ;hds,ds1,ds0
db 0 ;Cylinder
db 0 ;Head
db N_BOOT+1 ;Record (sector) of Group
db 0 ;Number of data bytes in sector
db N_BOOT+1 ;EOT
db 7 ;GPL
db 128 ;DTL
LRGHDR equ offset $ - offset read_ghdr
; Read remainder of track 0, sectors 6-26
read db F_RDAT
db 0 ;hds,ds1,ds0
db 0 ;Cylinder
db 0 ;Head
db N_BOOT+2 ;Record (sector) of BIOS
db 0 ;Number of data bytes in sector
db N_TRK ;Read to end of track
db 7 ;GPL
db 128 ;DTL
LREAD equ offset $ - offset read
; Disk Seek command for controller
seek db F_SEEK
db 0
db 1
LSEEK equ offset $ - offset seek
readid db F_RID + 040h
db 0
LREADID equ offset $ - offset readid
status rb 7 ;buffer for status result bytes
read1 dw read_128
dw read_256
dw read_512
dw read_1024
; Read function for single density (128 bytes/sec)
read_128 db F_RDAT
db 0 ;hds,ds1,ds0
db 1 ;Cylinder
db 0 ;Head
db 1 ;Record (sector) of BIOS
db 0 ;Number of data bytes in sector
db 26 ;Read to end of track
db 007h ;GPL
db 128 ;DTL
; Read function for double density (256 bytes/sec)
read_256 db F_RDAT + 040h
db 0 ;hds,ds1,ds0
db 1 ;Cylinder
db 0 ;Head
db 1 ;Record (sector) of BIOS
db 1 ;Number of data bytes in sector
db 26 ;Read to end of track
db 00Eh ;GPL
db 255 ;DTL
; Read function for double density (512 bytes/sec)
read_512 db F_RDAT + 040h
db 0 ;hds,ds1,ds0
db 1 ;Cylinder
db 0 ;Head
db 1 ;Record (sector) of BIOS
db 2 ;Number of data bytes in sector
db 15 ;Read to end of track
db 01Bh ;GPL
db 255 ;DTL
; Read function for double density (1024 bytes/sec)
read_1024 db F_RDAT + 040h
db 0 ;hds,ds1,ds0
db 1 ;Cylinder
db 0 ;Head
db 1 ;Record (sector) of BIOS
db 3 ;Number of data bytes in sector
db 8 ;Read to end of track
db 035h ;GPL
db 255 ;DTL
END