mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-22 16:04:18 +00:00
829 lines
21 KiB
Plaintext
829 lines
21 KiB
Plaintext
title 'Track Buffered BIOS - SBC204'
|
||
|
||
; 5 Jan 82 -jrp
|
||
|
||
|
||
; Copyright (C) 1980,1981
|
||
; Digital Research, Inc.
|
||
; Box 579, Pacific Grove
|
||
; California, 93950
|
||
;
|
||
; (Permission is hereby granted to use
|
||
; or abstract the following program in
|
||
; the implementation of CP/M, MP/M or
|
||
; CP/NET for the 8086 or 8088 Micro-
|
||
; processor)
|
||
|
||
|
||
true equ -1
|
||
false equ not true
|
||
|
||
; Track buffering equates...
|
||
|
||
host_sectsiz equ 128
|
||
host_spt equ 26
|
||
host_fsn equ 1
|
||
|
||
bdos_int equ 224
|
||
bios_code equ 2500h
|
||
ccp_offset equ 0000h
|
||
bdos_ofst equ 0B06h ;BDOS entry point
|
||
|
||
csts equ 0DAh ;i8251 status port
|
||
cdata equ 0D8h ; " data port
|
||
|
||
lsts equ 41h ;2651 No. 0 on BLC8538 status port
|
||
ldata equ 40h ; " " " " " data port
|
||
blc_reset equ 60h ;reset selected USARTS on BLC8538
|
||
|
||
|
||
;*********************************************
|
||
;* *
|
||
;* Intel iSBC 204 Disk Controller Ports *
|
||
;* *
|
||
;*********************************************
|
||
|
||
base204 equ 0a0h ;SBC204 assigned address
|
||
|
||
fdc_com equ base204+0 ;8271 FDC out command
|
||
fdc_stat equ base204+0 ;8271 in status
|
||
fdc_parm equ base204+1 ;8271 out parameter
|
||
fdc_rslt equ base204+1 ;8271 in result
|
||
fdc_rst equ base204+2 ;8271 out reset
|
||
dmac_adr equ base204+4 ;8257 DMA base address out
|
||
dmac_cont equ base204+5 ;8257 out control
|
||
dmac_scan equ base204+6 ;8257 out scan control
|
||
dmac_sadr equ base204+7 ;8257 out scan address
|
||
dmac_mode equ base204+8 ;8257 out mode
|
||
dmac_stat equ base204+8 ;8257 in status
|
||
fdc_sel equ base204+9 ;FDC select port (not used)
|
||
fdc_segment equ base204+10 ;segment address register
|
||
reset_204 equ base204+15 ;reset entire interface
|
||
|
||
max_retries equ 10 ;max retries on disk i/o
|
||
;before perm error
|
||
cr equ 0dh ;carriage return
|
||
lf equ 0ah ;line feed
|
||
|
||
cseg
|
||
org ccpoffset
|
||
ccp:
|
||
org bios_code
|
||
|
||
;*********************************************
|
||
;* *
|
||
;* BIOS Jump Vector for Individual Routines *
|
||
;* *
|
||
;*********************************************
|
||
|
||
jmp INIT ;Enter from BOOT ROM or LOADER
|
||
jmp WBOOT ;Arrive here from BDOS call 0
|
||
jmp CONST ;return console keyboard status
|
||
jmp CONIN ;return console keyboard char
|
||
jmp CONOUT ;write char to console device
|
||
jmp LISTOUT ;write character to list device
|
||
jmp PUNCH ;write character to punch device
|
||
jmp READER ;return char from reader device
|
||
jmp HOME ;move to trk 00 on cur sel drive
|
||
jmp SELDSK ;select disk for next rd/write
|
||
jmp SETTRK ;set track for next rd/write
|
||
jmp SETSEC ;set sector for next rd/write
|
||
jmp SETDMA ;set offset for user buff (DMA)
|
||
jmp READ ;read a 128 byte sector
|
||
jmp WRITE ;write a 128 byte sector
|
||
jmp LISTST ;return list status
|
||
jmp SECTRAN ;xlate logical->physical sector
|
||
jmp SETDMAB ;set seg base for buff (DMA)
|
||
jmp GETSEGT ;return offset of Mem Desc Table
|
||
jmp GETIOBF ;return I/O map byte (IOBYTE)
|
||
jmp SETIOBF ;set I/O map byte (IOBYTE)
|
||
|
||
|
||
|
||
;print signon message and initialize hardware
|
||
INIT:
|
||
mov ax,cs ;we entered with a JMPF so use
|
||
mov ds,ax ; CS: as the initial value of DS:,
|
||
mov es,ax ; and ES:
|
||
mov ss,ax ; use local stack during initialization
|
||
mov sp,offset stkbase
|
||
cld ;set forward direction
|
||
push ds ;save the DS register
|
||
mov ax,0
|
||
mov ds,ax
|
||
mov es,ax ;set ES and DS to zero
|
||
;setup interrupt 0 to address trap routine
|
||
mov int0_offset,offset int_trap
|
||
mov int0_segment,CS
|
||
mov di,4
|
||
mov si,0 ;then propagate
|
||
mov cx,510 ;trap vector to
|
||
rep movs ax,ax ;all 256 interrupts
|
||
;BDOS offset to proper interrupt
|
||
mov bdos_offset,bdos_ofst
|
||
pop ds ;restore the DS register
|
||
|
||
; Initialize the BLC 8538 printer port
|
||
mov al,0FFh
|
||
out blc_reset,al ;reset all usarts on 8538
|
||
mov al,4Eh
|
||
out ldata+2,al ;set usart 0 in async 8 bit mode
|
||
mov al,3Eh
|
||
out ldata+2,al ;set usart 0 to 9600 baud
|
||
mov al,37h
|
||
out ldata+3,al ;enable Tx/Rx, and set up RTS,DTR
|
||
mov bx,offset signon
|
||
call pmsg ;print signon message
|
||
|
||
call clear_flags ; initialize track buffering
|
||
|
||
mov cl,0 ;default to dr A: on coldstart
|
||
jmp ccp ;jump to cold start entry of CCP
|
||
|
||
WBOOT: jmp ccp+6 ;direct entry to CCP at command level
|
||
|
||
|
||
int_trap:
|
||
cli ;block interrupts
|
||
mov ax,cs
|
||
mov ds,ax ;get our data segment
|
||
mov bx,offset int_trp
|
||
call pmsg
|
||
hlt ;hardstop
|
||
|
||
|
||
;*********************************************
|
||
;* *
|
||
;* CP/M Character I/O Interface Routines *
|
||
;* Console is Usart (i8251a) on iSBC 86/12 *
|
||
;* at ports D8/DA *
|
||
;* *
|
||
;*********************************************
|
||
|
||
CONST: ;console status
|
||
in al,csts
|
||
and al,2
|
||
jz const_ret
|
||
or al,255 ;return non-zero if RDA
|
||
const_ret:
|
||
ret ;Receiver Data Available
|
||
|
||
CONIN: ;console input
|
||
call const
|
||
jz CONIN ;wait for RDA
|
||
in al,cdata
|
||
and al,7fh ;read data and remove parity bit
|
||
ret
|
||
|
||
CONOUT: ;console output
|
||
in al,csts
|
||
and al,1 ;get console status
|
||
jz CONOUT ;wait for TBE
|
||
mov al,cl
|
||
out cdata,al ;Transmitter Buffer Empty
|
||
ret ;then return data
|
||
|
||
LISTOUT: ;list device output
|
||
|
||
call LISTST
|
||
jz LISTOUT ;wait for printer not busy
|
||
mov al,cl
|
||
out ldata,al ;send char to TI 810
|
||
ret
|
||
|
||
LISTST: ;poll list status
|
||
|
||
in al,lsts
|
||
and al,81h ;look at both TxRDY and DTR
|
||
cmp al,81h
|
||
jnz zero_ret ;either false, printer is busy
|
||
or al,255 ;both true, LPT is ready
|
||
ret
|
||
|
||
PUNCH: ;not implemented in this configuration
|
||
READER:
|
||
mov al,1ah
|
||
ret ;return EOF for now
|
||
|
||
GETIOBF:
|
||
mov al,0 ;TTY: for consistency
|
||
ret ;IOBYTE not implemented
|
||
|
||
SETIOBF:
|
||
ret ;iobyte not implemented
|
||
|
||
zero_ret:
|
||
and al,0
|
||
ret ;return zero in AL and flags
|
||
|
||
; Routine to get and echo a console character
|
||
; and shift it to upper case
|
||
|
||
uconecho:
|
||
call CONIN ;get a console character
|
||
push ax
|
||
mov cl,al ;save and
|
||
call CONOUT
|
||
pop ax ;echo to console
|
||
cmp al,'a'
|
||
jb uret ;less than 'a' is ok
|
||
cmp al,'z'
|
||
ja uret ;greater than 'z' is ok
|
||
sub al,'a'-'A' ;else shift to caps
|
||
uret:
|
||
ret
|
||
|
||
; utility subroutine to print messages
|
||
|
||
pmsg:
|
||
mov al,[BX] ;get next char from message
|
||
test al,al
|
||
jz return ;if zero return
|
||
mov CL,AL
|
||
call CONOUT ;print it
|
||
inc BX
|
||
jmps pmsg ;next character and loop
|
||
|
||
|
||
|
||
;*********************************************
|
||
;* *
|
||
;* Disk Input/Output Routines *
|
||
;* *
|
||
;*********************************************
|
||
|
||
SELDSK: ;select disk given by register CL
|
||
mov cpm_disk,cl ; save the selected drive
|
||
mov bx,0000h
|
||
cmp cl,2 ;this BIOS only supports 2 disks
|
||
jnb return ;return w/ 0000 in BX if bad drive
|
||
;now, we need disk parameter address
|
||
mov ch,0
|
||
mov bx,cx ;BX = word(CL)
|
||
mov cl,4
|
||
shl bx,cl ;multiply drive code * 16
|
||
add bx,offset dp_base ;create offset from Disk Parameter Base
|
||
return:
|
||
ret
|
||
|
||
home:
|
||
test wr_flag,1 ! jnz home1 ; if the buffer is clean,
|
||
mov cur_disk,-1 ; insure we read the directory by invalidating
|
||
; the track buffer
|
||
home1:
|
||
mov cx,0 ; home is a settrk zero
|
||
|
||
settrk:
|
||
mov cpm_track,cx ; save track number for next operation
|
||
ret
|
||
|
||
setsec:
|
||
mov cpm_sec,cx ; save sector number for next operation
|
||
ret
|
||
|
||
|
||
|
||
setdma:
|
||
mov dma_offset,cx ; save DMA offset address
|
||
ret
|
||
setdmab:
|
||
mov dma_segment,cx ; save DMA segment address
|
||
ret
|
||
|
||
sectran:
|
||
mov bx,cx ; Put logical sector into dest. reg.
|
||
test dx,dx ; see if table address is zero
|
||
jz sectran_exit ; yeah, logical = physical
|
||
add bx,dx ; else, we need to fetch the
|
||
mov bl,[BX] ; actual sector number from the table
|
||
mov bh,0 ; zero high byte for good luck
|
||
sectran_exit:
|
||
ret
|
||
|
||
|
||
GETSEGT: ;return address of physical memory table
|
||
mov bx,offset seg_table
|
||
ret
|
||
|
||
|
||
|
||
read:
|
||
call track_setup
|
||
push es ; save the extra segment register
|
||
mov si,offset track_buffer ; source segment is systems DS:
|
||
add si,ax ; gives the offset into the buffer
|
||
les di,dma_longword ; point ES:DI at the users sector
|
||
rep movsw ; doit
|
||
pop es ; restore the extra segment
|
||
sub ax,ax ; make a zero return code
|
||
ret
|
||
|
||
write:
|
||
push cx ; save the write mode from the BDOS
|
||
call track_setup
|
||
push ax ; save buffer offset
|
||
push ds ; save the data segment
|
||
push es ; save the extra segment
|
||
mov bx,ds ! mov es,bx ; destination is our data segment
|
||
mov di,offset track_buffer ; destination is in track buffer
|
||
add di,ax ; plus appropriate offset
|
||
lds si,dma_longword ; source is users DMA address
|
||
rep movsw ; move that sector
|
||
pop es ; restore the extra segment
|
||
pop ds ; and the data segment registers
|
||
pop ax ; recover buffer offset
|
||
mov cx,host_sectsiz ; setup to divide by host sector size
|
||
sub dx,dx ; extend ax to 32 bits
|
||
div cx ; find out which host sector we changed
|
||
mov bx,ax ; put into index [BX]
|
||
mov sec_flags[BX],1 ; set the update flag for that sector
|
||
mov wr_flag,1 ; also set the dirty buffer flag
|
||
pop cx ; recover BDOS write code
|
||
cmp cl,1 ; is this a directory update ?
|
||
jne write_return ; no, we may leave dirty records
|
||
; in the buffer
|
||
call flush_buffer ; we have a directory write, need to
|
||
; flush the buffer to insure the
|
||
; disks integrity
|
||
write_return:
|
||
sub ax,ax ; never return BAD SECTOR code
|
||
ret
|
||
|
||
|
||
track_setup: ; common code for setting up reads and writes
|
||
|
||
mov al,cpm_disk ; see if selected disk is
|
||
cmp al,cur_disk ; the same as last time
|
||
jne wrong_track ; no, we have wrong track
|
||
|
||
mov ax,cpm_track ; see if desired track is same as
|
||
cmp ax,cur_track ; the track in the buffer
|
||
je correct_track ; same drive and track, we don't need to read
|
||
|
||
; Desired operation is on a different track then is in our buffer,
|
||
; So it will be nessecary to read in the desired track. First, we
|
||
; must check to see if any sectors of the current buffer are dirty.
|
||
|
||
wrong_track:
|
||
call flush_buffer ; write any old records, if nessecary
|
||
|
||
mov ax,cpm_track ; get desired track number
|
||
mov cur_track,ax ; make in new track
|
||
mov al,cpm_disk ; get desired disk number
|
||
mov cur_disk,al ; make it current drive
|
||
mov cur_dma_adr,offset track_buffer
|
||
; point dma offset at track buffer
|
||
mov cur_sec,host_fsn ; starting from first sector
|
||
call track_read ; load the track
|
||
|
||
correct_track:
|
||
mov ax,cpm_sec ; get the cp/m sector number
|
||
if (host_fsn ne 0)
|
||
sub ax,host_fsn ; correct if we start with sector one
|
||
endif
|
||
mov cl,7 ; log2(128)
|
||
shl ax,cl ; sector times 128 gives offset
|
||
mov cx,64 ! cld ; move 64 words forward
|
||
ret
|
||
|
||
|
||
flush_buffer:
|
||
test wr_flag,1 ; see if we have anything to write
|
||
jz no_flush ; no, skip scanning for dirty sectors
|
||
mov bx,host_fsn ; start at first host sector
|
||
mov cx,host_spt ; for host_spt sectors...
|
||
next_sect:
|
||
test sec_flags-host_fsn[BX],1 ; see if this sector has been changed
|
||
jz not_updated ; no, leave it alone
|
||
mov sec_flags-host_fsn[BX],0 ; zero the flag for next time
|
||
push bx ; save the registers
|
||
push cx
|
||
mov cur_sec,bx ; save host sector number
|
||
mov ax,host_sectsiz
|
||
if (host_fsn ne 0)
|
||
sub bx,host_fsn
|
||
endif
|
||
mul bx ; make track buffer offset
|
||
add ax,offset track_buffer ; make direct pointer
|
||
mov cur_dma_adr,ax ; save for write routine
|
||
call sector_write
|
||
pop cx
|
||
pop bx
|
||
not_updated:
|
||
inc bx
|
||
loop next_sect
|
||
no_flush:
|
||
mov wr_flag,0 ; clear the dirty buffer flag
|
||
ret
|
||
|
||
clear_flags: ; Clear all variables associated with the track buffer,
|
||
; so next operation will have to read a track.
|
||
; This is involves clearing all write flags and setting
|
||
; the old drive code to the invalid -1.
|
||
|
||
push es ; save extra segment
|
||
mov cur_disk,-1 ; insure initial pre-read
|
||
sub ax,ax ; make a zero
|
||
mov wr_flag,al ; clear the dirty buffer flag
|
||
mov di,offset sec_flags ; point to the update flag list
|
||
mov bx,ds ! mov es,bx ; ES <- DS
|
||
mov cx,host_spt ! cld ; set length and direction
|
||
rep stosb ; zero the sector update flags
|
||
mov cur_dma_seg,ds ; get our segment address
|
||
pop es ; recover extra segment
|
||
ret
|
||
|
||
|
||
|
||
track_READ:
|
||
mov io_com,4 ; read track takes 4 byte command
|
||
mov io_com+1,13h ; special read track command
|
||
jmps r_w_common
|
||
|
||
sector_WRITE:
|
||
mov io_com,3 ; write sector takes 3 byte command
|
||
mov io_com+1,0ah ; basic write sector command
|
||
|
||
r_w_common:
|
||
cmp cur_disk,1 ! jne not_first_b ; see if drive B
|
||
test b_first_flag,-1 ! jz not_first_b ; and first reference to B
|
||
call restore ; then restore drive B
|
||
mov b_first_flag,0 ; and clear flag
|
||
not_first_b:
|
||
mov bx,offset io_com ;point to command string
|
||
mov ax,cur_sec ; put sector in
|
||
mov sect,al ; iopb as 8 bits
|
||
mov ax,cur_track ; same with
|
||
mov trk,al ; track . .
|
||
|
||
; fall into execute and return
|
||
|
||
execute: ;execute command string.
|
||
;[BX] points to length,
|
||
; followed by Command byte,
|
||
; followed by length-1 parameter bytes
|
||
|
||
mov last_com,BX ;save command address for retries
|
||
outer_retry:
|
||
;allow some retrying
|
||
mov rtry_cnt,max_retries
|
||
retry:
|
||
mov BX,last_com
|
||
call send_com ;transmit command to i8271
|
||
; check status poll
|
||
|
||
mov BX,last_com
|
||
mov al,1[bx] ;get command op code
|
||
mov cx,0800h ;mask if it will be "int req"
|
||
cmp al,2ch
|
||
jb exec_poll ;ok if it is an interrupt type
|
||
mov cx,8080h ;else we use "not command busy"
|
||
and al,0fh
|
||
cmp al,0ch ;unless there isn't
|
||
mov al,0
|
||
ja exec_exit ; any result
|
||
;poll for bits in CH,
|
||
exec_poll: ; toggled with bits in CL
|
||
|
||
in al,fdc_stat ;read status
|
||
and al,ch
|
||
xor al,cl ; isolate what we want to poll
|
||
jz exec_poll ;and loop until it is done
|
||
|
||
;Operation complete,
|
||
in al,fdc_rslt ; see if result code indicates error
|
||
and al,1eh
|
||
jz exec_exit ;no error, then exit
|
||
;some type of error occurred . . .
|
||
cmp al,10h
|
||
je dr_nrdy ;was it a not ready drive ?
|
||
;no,
|
||
dr_rdy: ; then we just retry read or write
|
||
push ax ; save error code
|
||
call restore ; after physically homing this disk
|
||
pop ax ; recover error code
|
||
dec rtry_cnt
|
||
jnz retry ; up to 10 times
|
||
|
||
; retries do not recover from the
|
||
; hard error
|
||
|
||
mov ah,0
|
||
mov bx,ax ;make error code 16 bits
|
||
mov bx,errtbl[BX]
|
||
call pmsg ;print appropriate message
|
||
in al,cdata ;flush usart receiver buffer
|
||
call uconecho ;read upper case console character
|
||
cmp al,'C'
|
||
je wboot_l ;cancel
|
||
cmp al,'R'
|
||
je outer_retry ;retry 10 more times
|
||
cmp al,'I'
|
||
je z_ret ;ignore error
|
||
or al,255 ;set code for permanent error
|
||
exec_exit:
|
||
ret
|
||
|
||
dr_nrdy: ;here to wait for drive ready
|
||
call test_ready
|
||
jnz retry ;if it's ready now we are done
|
||
call test_ready
|
||
jnz retry ;if not ready twice in row,
|
||
mov bx,offset nrdymsg
|
||
call pmsg ;"Drive Not Ready"
|
||
nrdy01:
|
||
call test_ready
|
||
jz nrdy01 ;now loop until drive ready
|
||
jmps retry ;then go retry without decrement
|
||
zret:
|
||
and al,0
|
||
ret ;return with no error code
|
||
|
||
wboot_l: ;can't make it w/ a short leap
|
||
jmp WBOOT
|
||
|
||
;*********************************************
|
||
;* *
|
||
;* The i8271 requires a read status command *
|
||
;* to reset a drive-not-ready after the *
|
||
;* drive becomes ready *
|
||
;* *
|
||
;*********************************************
|
||
|
||
test_ready:
|
||
mov dh, 40h ;proper mask if dr 1
|
||
test sel_mask,80h
|
||
jnz nrdy2
|
||
mov dh, 04h ;mask for dr 0 status bit
|
||
nrdy2:
|
||
mov bx,offset rds_com
|
||
call send_com
|
||
dr_poll:
|
||
in al,fdc_stat ;get status word
|
||
test al,80h
|
||
jnz dr_poll ;wait for not command busy
|
||
in al,fdc_rslt ;get "special result"
|
||
test al,dh ;look at bit for this drive
|
||
ret ;return status of ready
|
||
|
||
|
||
restore: ;move selected disk to home position (Track 0)
|
||
mov bx,offset hom_com
|
||
call execute
|
||
jz restore_exit ;home drive and return if OK
|
||
mov bx,offset bad_hom ;else print
|
||
call pmsg ;"Home Error"
|
||
jmps restore ;and retry
|
||
restore_exit:
|
||
ret
|
||
|
||
;*********************************************
|
||
;* *
|
||
;* Send_com sends a command and parameters *
|
||
;* to the i8271: BX addresses parameters. *
|
||
;* The DMA controller is also initialized *
|
||
;* if this is a read or write *
|
||
;* *
|
||
;*********************************************
|
||
|
||
send_com:
|
||
in al,fdc_stat
|
||
test al,80h ;insure command not busy
|
||
jnz send_com ;loop until ready
|
||
|
||
;see if we have to initialize for a DMA operation
|
||
|
||
mov al,1[bx] ;get command byte
|
||
cmp al,13h
|
||
jne write_maybe ;if not a read it could be write
|
||
mov cl,40h
|
||
jmps init_dma ;is a read command, go set DMA
|
||
write_maybe:
|
||
cmp al,0ah
|
||
jne dma_exit ;leave DMA alone if not read or write
|
||
mov cl,80h ;we have write, not read
|
||
init_dma:
|
||
;we have a read or write operation, setup DMA controller
|
||
; (CL contains proper direction bit)
|
||
mov al,04h
|
||
out dmac_mode,al ;enable dmac
|
||
mov al,00
|
||
out dmac_cont,al ;send first byte to control port
|
||
mov al,cl
|
||
out dmac_cont,al ;load direction register
|
||
mov ax,cur_dma_adr
|
||
out dmac_adr,al ;send low byte of DMA
|
||
mov al,ah
|
||
out dmac_adr,al ;send high byte
|
||
mov ax,cur_dma_seg
|
||
out fdc_segment,al ;send low byte of segment address
|
||
mov al,ah
|
||
out fdc_segment,al ;then high segment address
|
||
dma_exit:
|
||
mov cl,[BX] ;get count
|
||
inc BX
|
||
mov al, 80h
|
||
cmp cur_disk,0
|
||
jne sel1 ;drive 1 if not zero
|
||
mov al, 40h ;else drive is 0
|
||
sel1: mov sel_mask,al ; save select mask
|
||
or al,[BX] ;merge command and drive code
|
||
out fdc_com,al ;send command byte
|
||
parm_loop:
|
||
dec cl
|
||
jz parm_exit ;no (more) parameters, return
|
||
inc BX ;point to (next) parameter
|
||
parm_poll:
|
||
in al,fdc_stat
|
||
test al,20h ;test "parameter register full" bit
|
||
jnz parm_poll ;idle until parm reg not full
|
||
mov al,[BX]
|
||
out fdc_parm,al ;send next parameter
|
||
jmps parm_loop ;go see if there are more parameters
|
||
parm_exit:
|
||
ret
|
||
|
||
;*********************************************
|
||
;* *
|
||
;* Data Areas *
|
||
;* *
|
||
;*********************************************
|
||
data_offset equ offset $
|
||
|
||
dseg
|
||
org data_offset ;contiguous with code segment
|
||
|
||
|
||
signon db cr,lf,cr,lf
|
||
db ' CP/M-86, 1 Feb 82 ',cr,lf,0
|
||
|
||
bad_hom db cr,lf,'Home Error',cr,lf,0
|
||
int_trp db cr,lf,'Interrupt Trap Halt',cr,lf,0
|
||
|
||
errtbl dw er0,er1,er2,er3
|
||
dw er4,er5,er6,er7
|
||
dw er8,er9,erA,erB
|
||
dw erC,erD,erE,erF
|
||
|
||
er0 db cr,lf,'Error Code 0 :',0
|
||
er1 db cr,lf,'Error Code 1 :',0
|
||
er2 db cr,lf,'Error Code 2 :',0
|
||
er3 db cr,lf,'Error Code 3 :',0
|
||
er4 db cr,lf,'Clock Error :',0
|
||
er5 db cr,lf,'Late DMA :',0
|
||
er6 db cr,lf,'ID CRC Error :',0
|
||
er7 db cr,lf,'Data CRC Error :',0
|
||
er8 db cr,lf,'Drive Not Ready :',0
|
||
er9 db cr,lf,'Write Protect :',0
|
||
erA db cr,lf,'Track 00 Not Found :',0
|
||
erB db cr,lf,'Write Fault :',0
|
||
erC db cr,lf,'Sector Not Found :',0
|
||
erD db cr,lf,'Error Code D :',0
|
||
erE db cr,lf,'Error Code E :',0
|
||
erF db cr,lf,'Error Code F :',0
|
||
|
||
nrdymsg equ er8
|
||
|
||
b_first_flag db -1
|
||
|
||
rtry_cnt db 0 ;disk error retry counter
|
||
last_com dw 0 ;address of last command string
|
||
cur_dma_adr dw 0 ;dma offset stored here
|
||
cur_dma_seg dw 0 ;dma segment stored here
|
||
sel_mask db 40h ;select mask, 40h or 80h
|
||
|
||
; Various command strings for i8271
|
||
|
||
io_com db 3 ;length (changed to 4 to read a track)
|
||
rd_wr db 0 ;read/write function code
|
||
trk db 0 ;track #
|
||
sect db 0 ;sector #
|
||
sec_len db 26 ;transfer 26 sectors on a track read
|
||
|
||
hom_com db 2,29h,0 ;home drive command
|
||
rds_com db 1,2ch ;read status command
|
||
|
||
; Track buffering variables
|
||
|
||
cpm_disk rb 1
|
||
cpm_track rw 1
|
||
cpm_sec rw 1
|
||
|
||
cur_disk rb 1
|
||
cur_track rw 1
|
||
cur_sec rw 1
|
||
|
||
dma_offset rw 1
|
||
dma_segment rw 1
|
||
dma_longword equ dword ptr dma_offset
|
||
|
||
bdos_wr_code rb 1
|
||
wr_flag rb 1
|
||
|
||
; System Memory Segment Table
|
||
|
||
segtable db 2 ;2 segments
|
||
dw tpa_seg ;1st seg starts after BIOS
|
||
dw tpa_len ;and extends to 08000
|
||
dw 1000h ;second is 10000 -
|
||
dw 1000h ;1FFFF (64k)
|
||
|
||
; include singles.lib ;read in disk definitions
|
||
; DISKS 2
|
||
dpbase equ $ ;Base of Disk Parameter Blocks
|
||
dpe0 dw xlt0,0000h ;Translate Table
|
||
dw 0000h,0000h ;Scratch Area
|
||
dw dirbuf,dpb0 ;Dir Buff, Parm Block
|
||
dw csv0,alv0 ;Check, Alloc Vectors
|
||
dpe1 dw xlt1,0000h ;Translate Table
|
||
dw 0000h,0000h ;Scratch Area
|
||
dw dirbuf,dpb1 ;Dir Buff, Parm Block
|
||
dw csv1,alv1 ;Check, Alloc Vectors
|
||
; DISKDEF 0,1,26,6,1024,243,64,64,2
|
||
;
|
||
; 1944: 128 Byte Record Capacity
|
||
; 243: Kilobyte Drive Capacity
|
||
; 64: 32 Byte Directory Entries
|
||
; 64: Checked Directory Entries
|
||
; 128: Records / Extent
|
||
; 8: Records / Block
|
||
; 26: Sectors / Track
|
||
; 2: Reserved Tracks
|
||
; 6: Sector Skew Factor
|
||
;
|
||
dpb0 equ offset $ ;Disk Parameter Block
|
||
dw 26 ;Sectors Per Track
|
||
db 3 ;Block Shift
|
||
db 7 ;Block Mask
|
||
db 0 ;Extnt Mask
|
||
dw 242 ;Disk Size - 1
|
||
dw 63 ;Directory Max
|
||
db 192 ;Alloc0
|
||
db 0 ;Alloc1
|
||
dw 16 ;Check Size
|
||
dw 2 ;Offset
|
||
xlt0 equ offset $ ;Translate Table
|
||
db 1,7,13,19
|
||
db 25,5,11,17
|
||
db 23,3,9,15
|
||
db 21,2,8,14
|
||
db 20,26,6,12
|
||
db 18,24,4,10
|
||
db 16,22
|
||
als0 equ (243+7)/8 ;Allocation Vector Size
|
||
css0 equ 16 ;Check Vector Size
|
||
; DISKDEF 1,0
|
||
;
|
||
; Disk 1 is the same as Disk 0
|
||
;
|
||
dpb1 equ dpb0 ;Equivalent Parameters
|
||
als1 equ als0 ;Same Allocation Vector Size
|
||
css1 equ css0 ;Same Checksum Vector Size
|
||
xlt1 equ xlt0 ;Same Translate Table
|
||
; ENDEF
|
||
;
|
||
; Uninitialized Scratch Memory Follows:
|
||
;
|
||
dirbuf rs 128 ;Directory Buffer
|
||
alv0 rs als0 ;Alloc Vector
|
||
csv0 rs css0 ;Check Vector
|
||
alv1 rs als1 ;Alloc Vector
|
||
csv1 rs css1 ;Check Vector
|
||
|
||
|
||
sec_flags rb host_spt
|
||
|
||
track_buffer rb host_spt*host_sectsiz
|
||
|
||
|
||
loc_stk rw 32 ;local stack for initialization
|
||
|
||
stkbase equ offset $
|
||
|
||
lastoff equ offset $
|
||
|
||
tpa_seg equ ((lastoff+07FFh)/0400h)*40h ; round off to 1K boundary
|
||
tpa_len equ 0800h - tpa_seg
|
||
|
||
db 0 ;fill last address for GENCMD
|
||
|
||
;*********************************************
|
||
;* *
|
||
;* Dummy Data Section for Interrupt Vectors *
|
||
;* *
|
||
;*********************************************
|
||
|
||
dseg 0 ;absolute low memory
|
||
org 0 ;(interrupt vectors)
|
||
|
||
int0_offset rw 1
|
||
int0_segment rw 1
|
||
|
||
; pad to system call vector
|
||
org bdos_int * 4
|
||
|
||
bdos_offset rw 1
|
||
bdos_segment rw 1
|
||
|
||
END
|
||
|