mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 00:14:25 +00:00
1579 lines
34 KiB
Plaintext
1579 lines
34 KiB
Plaintext
title '8086 Hardware Interface'
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* X I O S - 8 6
|
||
;* ===================
|
||
;*
|
||
;* MP/M-86 eXtended I/O System
|
||
;* for
|
||
;* Intel SBC 204 Floppy Diskette Interface
|
||
;*
|
||
;* Copyright (C) 1980, 1981
|
||
;* Digital Research, Inc.
|
||
;* Box 579, Pacific Grove
|
||
;* California, 93950
|
||
;*
|
||
;* The XIOS can be assembled in two forms
|
||
;* that are acceptable to GENSYS in building
|
||
;* an MP/M-86 II system.
|
||
;*
|
||
;* 8080 model:
|
||
;* -----------
|
||
;* Mixed code and data. The Code and Data
|
||
;* segments are the same. The code segment
|
||
;* is ORG'd at 1000h relative to the System
|
||
;* Data Area
|
||
;*
|
||
;* high +-----------------+\
|
||
;* | System Tables | |
|
||
;* +-----------------+ |
|
||
;* | XIOS (C and D) | > System Data
|
||
;* +-----------------+ |
|
||
;* | Sysdat | |
|
||
;* +-----------------+X
|
||
;* | System Code | > System Code
|
||
;* low +-----------------+/
|
||
;*
|
||
;* Separate Code and Data:
|
||
;* ----------------------
|
||
;*
|
||
;* The Code segment is separate from the
|
||
;* Data. The Code is ORG'd at 0000h and the
|
||
;* Data is ORG'd at 1000h.
|
||
;*
|
||
;* high +-----------------+\
|
||
;* | System Tables | |
|
||
;* +-----------------+ |
|
||
;* | XIOS Data | > System Data
|
||
;* +-----------------+ | Area
|
||
;* | Sysdat | |
|
||
;* +-----------------+X
|
||
;* | XIOS Code | |
|
||
;* +-----------------+ > System Code
|
||
;* | System Code | | Modules
|
||
;* low +-----------------+/
|
||
;*
|
||
;* This XIOS is presented as an example
|
||
;* hardware interface to an MP/M-86 system.
|
||
;* In many places in the code, more efficient
|
||
;* methods can be used.
|
||
;*
|
||
;* (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.)
|
||
;*
|
||
;*****************************************************
|
||
;*
|
||
;* REGISTER USAGE FOR XIOS INTERFACE ROUTINES:
|
||
;*
|
||
;* input: AL = function # (in entry)
|
||
;* CX = parameter
|
||
;* DX = second parameter
|
||
;* DS = sysdat (in entry and init)
|
||
;* = CS elsewhere
|
||
;* ES = User's Data Area
|
||
;*
|
||
;* output: AX = return
|
||
;* BX = AX (in exit)
|
||
;* ES,DS must be preserved though call
|
||
;*
|
||
;* NOTE: Some changes have been made in the
|
||
;* argument/return register usage from
|
||
;* the CP/M-86 BIOS.
|
||
;*
|
||
;*****************************************************
|
||
;*
|
||
;* SYSTEM EQUATES
|
||
;*
|
||
;*****************************************************
|
||
;
|
||
include system.lib
|
||
;
|
||
; conditional assembly switches
|
||
;
|
||
debug equ false
|
||
;*****MDISK SUPPORT*****
|
||
memdisk equ false
|
||
;***********************
|
||
|
||
cr equ 0dh ;carriage return
|
||
lf equ 0ah ;line feed
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* CHARACTER I/O EQUATES
|
||
;*
|
||
;*****************************************************
|
||
;
|
||
;
|
||
;base address of serial board
|
||
serbase equ 040h
|
||
;
|
||
nconsoles equ 4
|
||
nlists equ 1
|
||
;
|
||
;
|
||
; using Intel SBC 534 serial board
|
||
;
|
||
;port address to reset entire board
|
||
sereset equ serbase+0fh
|
||
;
|
||
;port address to set test mode
|
||
setestmode equ serbase+0eh
|
||
;
|
||
;port address to enable counter/timer
|
||
ctcenable equ serbase+0ch
|
||
;
|
||
;port address to enable uarts
|
||
uartenable equ serbase+0dh
|
||
;
|
||
;counter/timer mode addresses
|
||
ctc0to2md equ serbase+03h
|
||
ctc3to5md equ serbase+07h
|
||
ctc0mode equ 036h
|
||
ctc1mode equ 076h
|
||
ctc2mode equ 0b6h
|
||
ctc3mode equ 036h
|
||
;
|
||
;counter/timer load addresses
|
||
; and count values
|
||
ctc0ld equ serbase+00h
|
||
ctc1ld equ serbase+01h
|
||
ctc2ld equ serbase+02h
|
||
ctc3ld equ serbase+04h
|
||
cnt0vall equ 008h
|
||
cnt0valh equ 000h
|
||
cnt1vall equ 008h
|
||
cnt1valh equ 000h
|
||
cnt2vall equ 008h
|
||
cnt2valh equ 000h
|
||
cnt3vall equ 008h
|
||
cnt3valh equ 000h
|
||
;
|
||
;uart mode and command
|
||
;
|
||
u0mode equ 04eh
|
||
u1mode equ 04eh
|
||
u2mode equ 04eh
|
||
u3mode equ 04eh
|
||
u0cmd equ 037h
|
||
u1cmd equ 037h
|
||
u2cmd equ 037h
|
||
u3cmd equ 037h
|
||
;
|
||
; console i/o and status ports
|
||
; in and out status masks
|
||
;
|
||
;
|
||
; console 0
|
||
;
|
||
c0ioport equ 0d8h
|
||
c0stport equ 0dah
|
||
c0inmsk equ 02h
|
||
c0outmsk equ 01h
|
||
;
|
||
; console 1
|
||
;
|
||
c1ioport equ serbase+02h
|
||
c1stport equ serbase+03h
|
||
c1inmsk equ 002h
|
||
c1outmsk equ 001h
|
||
;
|
||
; console 2
|
||
;
|
||
c2ioport equ serbase+04h
|
||
c2stport equ serbase+05h
|
||
c2inmsk equ 002h
|
||
c2outmsk equ 001h
|
||
;
|
||
; console 3
|
||
;
|
||
c3ioport equ serbase+06h
|
||
c3stport equ serbase+07h
|
||
c3inmsk equ 002h
|
||
c3outmsk equ 001h
|
||
;
|
||
; list 0
|
||
;
|
||
l0ioport equ serbase+00h
|
||
l0stport equ serbase+01h
|
||
l0inmsk equ 002h
|
||
l0outmsk equ 081h
|
||
;
|
||
;
|
||
;
|
||
;*****************************************************
|
||
;*
|
||
;* DISK I/O EQUATES
|
||
;*
|
||
;* Intel iSBC 204 Disk Controller Ports
|
||
;*
|
||
;*****************************************************
|
||
|
||
base204 equ 0a0h ;SBC204 assigned addr
|
||
|
||
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 adr 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
|
||
fdc_segment equ base204+10 ;segment addr register
|
||
reset_204 equ base204+15 ;reset interface
|
||
|
||
max_retries equ 10 ;retries on disk i/o
|
||
;before perm error
|
||
;*****MDISK SUPPORT*****
|
||
mdiskbase equ 2000h ;base address of mdisk
|
||
;***********************
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* SUP/RTM EQUATES
|
||
;*
|
||
;*****************************************************
|
||
|
||
tracebit equ 0100H
|
||
|
||
f_dispatch equ 142 ; MPM dispatch func #
|
||
f_terminate equ 143 ; MPM terminate func #
|
||
f_polldev equ 131 ; MPM polldevice func #
|
||
f_flagset equ 133 ; MPM flagset func #
|
||
|
||
p_flag equ word ptr 06H ; PD flag field
|
||
p_name equ byte ptr 08H ; PD Name field
|
||
p_cns equ byte ptr 020H ; PD console field
|
||
pf_keep equ 02H ; KEEP bit in p_flag
|
||
|
||
;flag assignments
|
||
|
||
tick_flag equ 1
|
||
sec_flag equ 2
|
||
|
||
;device # assignments for POLL DEV
|
||
|
||
c0indev equ 00h ;console 0 input device
|
||
c1indev equ 01h ;console 1 input device
|
||
c2indev equ 02h ;console 2 input device
|
||
c3indev equ 03h ;console 3 input device
|
||
c0outdev equ 04h ;console 0 output device
|
||
c1outdev equ 05h ;console 1 output device
|
||
c2outdev equ 06h ;console 2 output device
|
||
c3outdev equ 07h ;console 3 output device
|
||
l0outdev equ 08h ;list 0 output device
|
||
flpy_poll_dev equ 09h ;floppy disk poll device
|
||
|
||
;
|
||
; system data area must preceed code
|
||
; area for 8080 model of the XIOS
|
||
;
|
||
include sysdat.lib
|
||
|
||
endsysdat equ ((offset $)+0fh) AND 0fff0h
|
||
|
||
CSEG
|
||
org offset endsysdat
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* SYSTEM CODE AREA
|
||
;*
|
||
;* XIOS JUMP TABLE
|
||
;*
|
||
;*****************************************************
|
||
|
||
jmp init ;system initialization
|
||
jmp entry ;xios entry point
|
||
|
||
sysdat dw 0 ;Sysdat Segment
|
||
supervisor equ offset $
|
||
rw 2
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* UTILITY SUBROUTINES
|
||
;*
|
||
;*****************************************************
|
||
|
||
;====
|
||
pmsg:
|
||
;====
|
||
; print message on current console until null (char 0)
|
||
; input: BX = address of message
|
||
|
||
;put running processes console
|
||
;number in DL
|
||
|
||
pushf ! cli
|
||
push stoppoll
|
||
mov stoppoll,true
|
||
push ds ! mov ds,sysdat ;DS = system data area
|
||
mov si,rlr ;SI -> current pd
|
||
mov dl,p_cns[si] ;DL = def console #
|
||
pop ds
|
||
ploop:
|
||
mov al,[bx] ; get next char
|
||
cmp al,0 ! jz pmsg_ret ; return if zero
|
||
mov cl,al ; CL = character
|
||
push dx ! push bx ; save console,posit.
|
||
call conout ; print it
|
||
pop bx ! pop dx ; restore posit.,cons.
|
||
inc bx ! jmps ploop ; inc and loop
|
||
pmsg_ret:
|
||
pop stoppoll
|
||
popf ! ret ; end of message
|
||
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* INTERRUPT ROUTINES
|
||
;*
|
||
;*****************************************************
|
||
|
||
;these variables must be in code segment
|
||
|
||
tickint_ss dw 0
|
||
tickint_sp dw 0
|
||
ax_save dw 0
|
||
zero dw 0
|
||
|
||
;=======
|
||
tickint:
|
||
;=======
|
||
; Interrupt handler for tick interrupts
|
||
|
||
;save context
|
||
push ds ! mov ds,sysdat
|
||
mov tickint_ss,ss
|
||
mov tickint_sp,sp
|
||
mov ax_save,ax
|
||
mov ax,cs
|
||
mov ss,ax
|
||
mov sp,offset tickint_tos
|
||
push ax_save
|
||
push bx ! push cx ! push dx
|
||
push bp ! push si ! push di ! push es
|
||
mov ds,ax
|
||
|
||
; check to set second flag
|
||
|
||
dec tick_count ! jnz do_tick_flag
|
||
mov tick_count,60
|
||
mov dx,sec_flag
|
||
mov cl,f_flagset ! call supif
|
||
do_tick_flag:
|
||
; check to set tick flag
|
||
|
||
cmp clockon,true ! jne tick_done
|
||
mov dx,tick_flag
|
||
mov cl,f_flagset ! call supif
|
||
|
||
tick_done: ;restore context
|
||
pop es ! pop di ! pop si ! pop bp
|
||
pop dx ! pop cx ! pop bx ! pop ax
|
||
mov ss,tickint_ss
|
||
mov sp,tickint_sp
|
||
;force dispatch
|
||
pop ds
|
||
; jmp intdisp
|
||
|
||
;=======
|
||
intdisp:
|
||
;=======
|
||
|
||
jmpf cs:dword ptr .dispatcher
|
||
|
||
;========
|
||
int_trap: ;unknown interrupts go here ...
|
||
;========
|
||
; We will terminate the process that caused this
|
||
; after writing a message to the process's default
|
||
; console. If the process is in KEEP mode, we will
|
||
; force it to terminate anyway...
|
||
;
|
||
; We don't need to save any registers since we are
|
||
; not going to return to the process.
|
||
|
||
|
||
mov ax,cs
|
||
mov ds,sysdat
|
||
|
||
; print first 6 chars of PD Name
|
||
mov bx,rlr
|
||
add bx,p_name
|
||
mov byte ptr 6[bx],':'
|
||
mov byte ptr 7[bx],0
|
||
call pmsg
|
||
|
||
; print Illegal Interrupt message
|
||
mov bx,offset int_trp
|
||
call pmsg
|
||
|
||
; terminate process
|
||
mov bx,rlr
|
||
and p_flag[bx],not pf_keep
|
||
mov cx,f_terminate
|
||
mov dx,0ffffh
|
||
int 224
|
||
hlt ;hard stop
|
||
;the terminate returned !!!!
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* INITIALIZATION CODE AREA
|
||
;*
|
||
;* Inter-Module Interface Routines
|
||
;*
|
||
;*****************************************************
|
||
|
||
;====
|
||
init: ; XIOS system initialization routine.
|
||
;====
|
||
; The INIT routine initializes all necessary
|
||
; hardware
|
||
;
|
||
; -called from SUP init. routine with CALLF
|
||
;
|
||
; -Interrupt 224 is reinitialized by SUP later
|
||
; -It is okay to turn on interrupts at any time
|
||
; a STI is performed immediately after RETF
|
||
;
|
||
; -Current Stack has about 10 levels here. Must do a
|
||
; local stack switch if more is needed.
|
||
;
|
||
; -If assembled (GENCMD'd) with 8080 model,
|
||
; CS=DS=Sysdat
|
||
; -If assembled with separate Code and Data,
|
||
; CS=Code (ORGed at 0) DS=Sysdat
|
||
;
|
||
; -This example shows 8080 model
|
||
;
|
||
; input: DS = sysdat segment address
|
||
;
|
||
;-----------------------------------------------------
|
||
; SYSTEM INITIALIZATION AREA
|
||
;-----------------------------------------------------
|
||
;Save sysdat seg addr in case we need
|
||
;to see system data area. Set DS=CS
|
||
|
||
push ds ;save DS on stack for
|
||
;exit
|
||
|
||
;initialize segment registers
|
||
|
||
mov sysdat,ds ; save sysdat for
|
||
; sysdat access
|
||
|
||
;place copy of SUPMOD in data segment
|
||
;into Code Segment (supervisor)
|
||
|
||
mov bx,offset supmod
|
||
mov si,supervisor
|
||
mov ax,[bx] ! mov cs:[si],ax
|
||
mov ax,2[bx] ! mov cs:2[si],ax
|
||
|
||
;Make copy of Interrupt Routines
|
||
;access point to dispatcher in
|
||
;Code Segment
|
||
|
||
push cs ! pop ds ; DS = CS
|
||
cld ;set forward direction
|
||
|
||
;stack switch since we are doing
|
||
; i/o with polled devices when
|
||
; printing login message
|
||
; interrupts are known to be off
|
||
; here so no need to save flags,
|
||
; disable, and restore flags
|
||
|
||
mov initss,ss
|
||
mov initsp,sp
|
||
mov ax,cs ! mov ss,ax
|
||
mov sp,offset initstack
|
||
|
||
|
||
; Setup all interrupt vectors in low
|
||
; memory to address trap
|
||
|
||
if not debug
|
||
|
||
push ds
|
||
push es ;ES must be saved
|
||
mov ax,0
|
||
mov ds,ax
|
||
mov es,ax ;set ES and DS to zero
|
||
|
||
;setup interrupt 0 to trap routine
|
||
|
||
mov .0,offset int_trap
|
||
mov .2,CS
|
||
mov di,4
|
||
mov si,0 ;then propagate
|
||
mov cx,510 ;trap vector to
|
||
rep movsw ;int 255
|
||
|
||
pop es
|
||
pop ds ;restore DS,ES
|
||
|
||
endif
|
||
|
||
;-----------------------------------------------------
|
||
; CHARACTER I/O INITIALIZATION
|
||
;-----------------------------------------------------
|
||
;
|
||
;
|
||
;*********************************************
|
||
;*
|
||
;* sbc 534 serial board initialization
|
||
;*
|
||
;*********************************************
|
||
;
|
||
mov al,0
|
||
out sereset,al ;reset serial board
|
||
out setestmode,al ;set test mode to off
|
||
out ctcenable,al ;enable ctc addressing
|
||
;
|
||
;start clock for port 0
|
||
mov al,ctc0mode ! out ctc0to2md,al
|
||
mov al,cnt0vall ! out ctc0ld,al
|
||
mov al,cnt0valh ! out ctc0ld,al
|
||
;
|
||
;start clock for port 1
|
||
mov al,ctc1mode ! out ctc0to2md,al
|
||
mov al,cnt1vall ! out ctc1ld,al
|
||
mov al,cnt1valh ! out ctc1ld,al
|
||
;
|
||
;start clock for port 2
|
||
mov al,ctc2mode ! out ctc0to2md,al
|
||
mov al,cnt2vall ! out ctc2ld,al
|
||
mov al,cnt2valh ! out ctc2ld,al
|
||
;
|
||
;start clock for port 3
|
||
mov al,ctc3mode ! out ctc3to5md,al
|
||
mov al,cnt3vall ! out ctc3ld,al
|
||
mov al,cnt3valh ! out ctc3ld,al
|
||
;
|
||
out uartenable,al ;enable uart addressing
|
||
;
|
||
;initialize port 0
|
||
mov al,u0mode ! out l0stport,al
|
||
mov al,u0cmd ! out l0stport,al
|
||
;
|
||
;initialize port 1
|
||
mov al,u1mode ! out c1stport,al
|
||
mov al,u1cmd ! out c1stport,al
|
||
;
|
||
;initialize port 2
|
||
mov al,u2mode ! out c2stport,al
|
||
mov al,u2cmd ! out c2stport,al
|
||
;
|
||
;initialize port 3
|
||
mov al,u3mode ! out c3stport,al
|
||
mov al,u3cmd ! out c3stport,al
|
||
;
|
||
;
|
||
;-----------------------------------------------------
|
||
; DISK I/O INITIALIZATION
|
||
;-----------------------------------------------------
|
||
;***** MDISK SUPPORT *****
|
||
if memdisk
|
||
;initialize MDISK
|
||
|
||
mov cx,mdiskbase
|
||
push es ! mov es,cx
|
||
mov di,0 ! mov ax,0e5e5h
|
||
cmp es:[di],ax ! je mdisk_end
|
||
mov cx,2000h
|
||
rep stos ax
|
||
mdisk_end:
|
||
pop es
|
||
;
|
||
endif
|
||
;*************************
|
||
|
||
;-----------------------------------------------------
|
||
; SUP/RTM INITIALIZATION
|
||
;-----------------------------------------------------
|
||
;Initialize Clock Tick
|
||
|
||
if not debug
|
||
;set up tick interrupt vector
|
||
;tick causes interrupt 22
|
||
sub ax,ax ! push ds ! mov ds,ax
|
||
mov word ptr .088h,offset tick_int
|
||
mov word ptr .08ah,cs
|
||
pop ds
|
||
;setup ticks to occur every
|
||
; 1/60th of a second
|
||
mov tick_count,60
|
||
mov al,034h ! out 0d6h,al ;PIT ch.0=mode 2
|
||
;set # of 1/1.2288e6 seconds
|
||
;20480=5000h=1/60th second
|
||
mov al,000h ! out 0d0h,al ;low count
|
||
mov al,050h ! out 0d0h,al ;high count
|
||
;set up interrupt controller
|
||
mov al,013h ! out 0c0h,al ;ICW1
|
||
mov al,020h ! out 0c2h,al ;ICW2
|
||
; = base interrupt
|
||
mov al,00fh ! out 0c2h,al ;ICW4,
|
||
; auto EOI,
|
||
; 8086 mode
|
||
mov al,0fbh ! out 0c2h,al ;OCW2,
|
||
; interrupt mask,
|
||
; only 2
|
||
endif
|
||
;-----------------------------------------------------
|
||
; INITIALIZATION EXIT
|
||
;-----------------------------------------------------
|
||
;allow poll_device mechanism to work
|
||
|
||
mov stoppoll,false
|
||
|
||
;print optional message on Console 0
|
||
|
||
mov bx,offset signon
|
||
call pmsg
|
||
|
||
;restore stack
|
||
; all stack switches must be in
|
||
; critical areas (interrupts off).
|
||
|
||
pushf ! pop ax
|
||
cli
|
||
mov ss,initss
|
||
mov sp,initsp
|
||
push ax
|
||
popf
|
||
|
||
;return back to BDOS
|
||
pop ds
|
||
retf
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* ENTRY POINT CODE AREA
|
||
;*
|
||
;*****************************************************
|
||
;===== ==================
|
||
entry: ; XIOS Entry Point
|
||
;===== ==================
|
||
; All calls to the XIOS routines enter through here
|
||
; with a CALLF. Must return with a RETF
|
||
; input: AL = function number
|
||
; CX = parameter
|
||
; DX = 2nd parameter
|
||
; output: AX = BX = return
|
||
|
||
cld ;clear D flag
|
||
mov bx,cs ! mov ds,bx ; (only 8080 model)
|
||
mov ah,0 ! shl ax,1 ;call routine
|
||
mov bx,ax ! call functab[bx]
|
||
mov bx,ax ;BX=AX
|
||
retf ;All Done
|
||
|
||
;===== ======================
|
||
supif: ; Supervisor Interface
|
||
;===== ======================
|
||
;
|
||
; input: CX = function #
|
||
; DX = parameter
|
||
; DS = parameter segment if address
|
||
; ES = user data area
|
||
; output: BX = AX = return
|
||
; CX = error code for RTM functions
|
||
; ES = return segment if address
|
||
|
||
mov ch,0
|
||
callf cs:dword ptr .supervisor ! ret
|
||
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* MP/M XIOS functions
|
||
;*
|
||
;*****************************************************
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* CHARACTER I/O CODE AREA
|
||
;*
|
||
;*****************************************************
|
||
|
||
;=====
|
||
const: ; Function 0: Console Status
|
||
;=====
|
||
; input: CL = console device number
|
||
; output: AL = 0ffh if ready
|
||
; = 000h if not ready
|
||
|
||
mov ch,0 ! shl cx,1
|
||
mov bx,cx
|
||
mov dx,consttbl[bx]
|
||
mov bl,dh ;BL = status mask
|
||
mov dh,0 ;DX = status port address
|
||
|
||
; find input status for console device
|
||
|
||
in al,dx
|
||
and al,bl
|
||
mov al,0
|
||
jz badstatus
|
||
mov al,0ffh
|
||
badstatus:
|
||
ret
|
||
|
||
;=====
|
||
conin: ; Function 1: Console Input
|
||
;=====
|
||
; input: CL = console device number
|
||
; output: AL = character
|
||
|
||
mov ch,0 ! shl cx,1
|
||
mov bx,cx
|
||
mov dx,conintbl[bx]
|
||
mov bl,dh ;BL = poll device no.
|
||
mov dh,0 ;DX = i/o port address
|
||
|
||
; input routine for console device
|
||
|
||
mov bh,0 ! push dx
|
||
call rtm_poll ! pop dx
|
||
in al,dx
|
||
;and al,07fh ;CP/NET uses parity bit
|
||
ret
|
||
|
||
;======
|
||
conout: ; Function 2: Console Output
|
||
;======
|
||
; input: CL = character
|
||
; DL = console device #
|
||
; output: None
|
||
|
||
mov dh,0 ! shl dx,1
|
||
mov bx,dx
|
||
mov dx,conouttbl[bx]
|
||
mov bl,dh ;BL = poll device no.
|
||
mov dh,0 ;DX = i/o port address
|
||
|
||
; output routine for console device
|
||
|
||
push cx ! push dx
|
||
mov bh,0 ! call rtm_poll
|
||
pop dx ! pop ax
|
||
out dx,al ! ret
|
||
|
||
;=====
|
||
plist: ; Function 3: List Output
|
||
;=====
|
||
; input: CL = character
|
||
; DL = list device #
|
||
; output: None
|
||
|
||
mov dh,0 ! shl dx,1
|
||
mov bx,dx
|
||
mov dx,louttbl[bx]
|
||
mov bl,dh ;BL = poll device no.
|
||
mov dh,0 ;DX = list port address
|
||
|
||
; output routine for list device
|
||
|
||
push cx ! push dx
|
||
mov bh,0 ! call rtm_poll
|
||
pop dx ! pop ax
|
||
out dx,al ! ret
|
||
|
||
;=====
|
||
punch: ; Function 4: Punch Output
|
||
reader: ; Function 5: Reader Output
|
||
;======
|
||
; PUNCH and READER devices are not supported
|
||
; under MP/M-86
|
||
; input: CL = character
|
||
; output: AL = character (control Z)
|
||
|
||
mov al,1ah ! ret ; return EOF
|
||
|
||
;------
|
||
plstst: ; convert poll device no.
|
||
;------ ; to list device no.
|
||
|
||
sub cl,nconsoles * 2
|
||
; fall into list status
|
||
|
||
;======
|
||
listst: ; Function 13: List Status
|
||
;======
|
||
; input: CL = list device number
|
||
; output: AL = 0ffh if ready
|
||
; = 000h if not ready
|
||
|
||
mov ch,0 ! shl cx,1
|
||
mov bx,cx
|
||
mov dx,loutsttbl[bx]
|
||
mov bl,dh ;BL = status mask
|
||
mov dh,0 ;DX = output port address
|
||
|
||
; find output status of List device
|
||
|
||
in al,dx
|
||
and al,bl
|
||
cmp al,bl
|
||
mov al,0ffh
|
||
jz gstat
|
||
mov al,0
|
||
gstat: ret
|
||
|
||
;==========
|
||
maxconsole: ; Function 20: Maximum Consoles
|
||
;==========
|
||
; input: None
|
||
; output: AL = number of consoles
|
||
|
||
mov ax,nconsoles ! ret
|
||
|
||
;=======
|
||
maxlist: ; Function 21: Maximum List Devices
|
||
;=======
|
||
; input: None
|
||
; output: AL = number of consoles
|
||
|
||
mov ax,nlists ! ret
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* DISK I/O CODE AREA
|
||
;*
|
||
;*****************************************************
|
||
|
||
;====
|
||
HOME: ; Function 6: Home
|
||
;====
|
||
; move selected disk to home position (Track 0)
|
||
; If there is Hardware home function, it should
|
||
; be done here otherwise, do a settrk to 0
|
||
; input: None
|
||
; output: None
|
||
|
||
mov trk,0 ;set disk i/o to track zero
|
||
xor bx,bx
|
||
mov bl,disk ;index into disk home routine
|
||
shl bx,1
|
||
jmp dskhomtbl[bx]
|
||
|
||
flpy_home:
|
||
mov bx,offset hom_com
|
||
call execute ;home drive
|
||
hom_ret:
|
||
ret ; and return
|
||
|
||
;======
|
||
SELDSK: ; Function 7: Select Disk
|
||
;======
|
||
; input: CL = disk to be selected
|
||
; output: AX = 0 if illegal disk
|
||
; = offset of DPH relative from
|
||
; XIOS Data Segment
|
||
|
||
xor ax,ax ;zero registers ax and bx
|
||
mov bx,ax
|
||
mov ch,0 ;translate logical disk
|
||
mov si,cx ;to physical disk device
|
||
mov al,dtrntbl[si]
|
||
cmp al,0ffh ;valid disk select?
|
||
jz sel_ret ;if not valid return
|
||
;else compute the
|
||
; disk parameter address
|
||
mov disk,al ;save physical drive no.
|
||
mov cl,4
|
||
shl al,cl ;multiply by 16
|
||
add ax,offset dp_base
|
||
mov bx,ax
|
||
sel_ret:
|
||
mov ax,bx
|
||
ret
|
||
|
||
;======
|
||
SETTRK: ; Function 8: Set Track
|
||
;======
|
||
; input: CX = Track Number
|
||
; output: None
|
||
|
||
mov trk,cl ;we only use 8 bits of
|
||
; track address
|
||
ret
|
||
|
||
;======
|
||
SETSEC: ; Function 9: Set Sector
|
||
;======
|
||
; input: CX = Sector Number
|
||
; output: None
|
||
|
||
mov sect,cl ;we only use 8 bits of
|
||
; sector address
|
||
ret
|
||
|
||
;======
|
||
SETDMA: ; Function 10: Set DMA Offset
|
||
;======
|
||
; input: CX = Offset of DMA buffer
|
||
; output: None
|
||
|
||
mov dma_adr,CX
|
||
ret
|
||
|
||
;*********************************************
|
||
;* *
|
||
;* All disk I/O parameters are setup: the *
|
||
;* Read and Write entry points transfer one *
|
||
;* sector of 128 bytes to/from the current *
|
||
;* DMA address using the current disk drive *
|
||
;* *
|
||
;*********************************************
|
||
|
||
;====
|
||
READ: ; Function 11: Read
|
||
;====
|
||
; input: None
|
||
; output: AL = 00h if no error occured
|
||
; = 01h if error occured
|
||
|
||
xor bx,bx
|
||
mov bl,disk ;index into disk read routine
|
||
shl bx,1
|
||
jmp dskrdtbl[bx]
|
||
|
||
;***** MDISK SUPPORT *****
|
||
if memdisk
|
||
;
|
||
mdsk_read:
|
||
call mdisk_calc
|
||
mov di,dma_adr ! mov si,0
|
||
push es ! mov es,dma_seg
|
||
push ds ! mov ds,ax
|
||
mov cx,64 ! rep movs ax,ax
|
||
pop ds ! pop es
|
||
mov ax,0 ! ret
|
||
;
|
||
endif
|
||
;*************************
|
||
|
||
flpy_read:
|
||
mov al,12h ;basic read sector command
|
||
jmps r_w_common
|
||
|
||
;***** MDISK SUPPORT *****
|
||
if memdisk
|
||
;
|
||
mdisk_calc:
|
||
mov bh,0 ! mov bl,trk
|
||
mov ax,26 ! mul bx
|
||
mov bh,0 ! mov bl,sect
|
||
add ax,bx ! mov cl,3
|
||
shl ax,cl ! add ax,mdiskbase+1
|
||
ret
|
||
;
|
||
endif
|
||
;*************************
|
||
|
||
;=====
|
||
WRITE: ; Function 12: Write
|
||
;=====
|
||
; input: CL = 0 - deferred write
|
||
; 1 - non-deferred write
|
||
; 2 - def wrt 1st sect unalloc blk
|
||
; 3 - non-def 1st sect unalloc blk
|
||
; output: AL = 00h if no error occured
|
||
; = 01h if error occured
|
||
; = 02h if read/only disk
|
||
|
||
xor bx,bx
|
||
mov bl,disk ;index into disk write routine
|
||
shl bx,1
|
||
jmp dskwrttbl[bx]
|
||
|
||
;***** MDISK SUPPORT *****
|
||
if memdisk
|
||
;
|
||
mdsk_write:
|
||
call mdisk_calc
|
||
mov di,0 ! mov si,dma_adr
|
||
push es ! mov es,ax
|
||
push ds ! mov ds,dma_seg
|
||
mov cx,64 ! rep movs ax,ax
|
||
pop ds ! pop es
|
||
mov ax,0 ! ret
|
||
;
|
||
endif
|
||
;*************************
|
||
|
||
flpy_write:
|
||
mov al,0ah ;basic write sector command
|
||
|
||
r_w_common:
|
||
mov bx,offset io_com ;point to command string
|
||
mov byte ptr 1[BX],al ;put command into string
|
||
|
||
; fall into execute and return
|
||
|
||
execute: ;execute command string.
|
||
;[BX] points to length,
|
||
; followed by Command byte,
|
||
; followed by length-1 parameter bytes
|
||
|
||
mov al,80h
|
||
test disk,1 ;A drive is even phys. drive
|
||
jnz exec1 ;B drive is odd phys. drive
|
||
mov al,40h
|
||
exec1: mov sel_mask,al
|
||
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 flpy_poll ;ok if it is an interrupt type
|
||
mov cx,8080h ;else 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,
|
||
flpy_poll: ; toggled with bits in CL
|
||
mov status_mask,cx
|
||
mov bx,flpy_poll_dev ! call rtm_poll
|
||
;Operation complete,
|
||
in al,fdc_rslt ; see if result indicates
|
||
and al,1eh ; an error
|
||
jz exec_exit ;no error, then exit
|
||
;some type of error occurred
|
||
cmp al,10h
|
||
jne dr_rdy ;was it a not ready drive ?
|
||
;yes, here to wait for drive ready
|
||
call test_ready
|
||
jnz dr_rdy ;if ready try again
|
||
call test_ready
|
||
;if not ready twice in row,
|
||
dr_rdy: ; then we just retry read or write
|
||
dec rtry_cnt
|
||
jnz retry ; up to 10 times
|
||
|
||
; retries do not recover from the
|
||
; hard error
|
||
|
||
cmp al,012h ; check if r/o disk
|
||
jne err_exit
|
||
mov al,02h ; return r/o error code
|
||
ret
|
||
err_exit:
|
||
mov ah,0 ;setup error table index
|
||
mov bx,ax ;make error code 16 bits
|
||
mov bx,errtbl[BX]
|
||
call pmsg ;print appropriate message
|
||
mov al,01h ;set code for permanent error
|
||
exec_exit:
|
||
ret
|
||
|
||
;*********************************************
|
||
;* *
|
||
;* 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
|
||
and al,01eh
|
||
ret ;return status of ready
|
||
|
||
;*********************************************
|
||
;* *
|
||
;* 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
|
||
|
||
;check to initialize for a DMA operation
|
||
|
||
mov al,1[bx] ;get command byte
|
||
cmp al,12h
|
||
jne write_maybe ;if not read it maybe write
|
||
mov cl,40h ;is a read command, go set DMA
|
||
jmps init_dma
|
||
write_maybe:
|
||
cmp al,0ah
|
||
jne dma_exit ;leave DMA if not read/write
|
||
mov cl,80h ;we have write, not read
|
||
init_dma:
|
||
; 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 ;1st byte to ctrl port
|
||
mov al,cl
|
||
out dmac_cont,al ;load direction register
|
||
mov ax,dma_adr
|
||
out dmac_adr,al ;send low byte of DMA
|
||
mov al,ah
|
||
out dmac_adr,al ;send high byte
|
||
mov ax,dma_seg
|
||
out fdc_segment,al ;send low byte of seg addr
|
||
mov al,ah
|
||
out fdc_segment,al ;then high segment address
|
||
dma_exit:
|
||
mov cl,[BX] ;get count
|
||
inc BX
|
||
mov al,[BX] ;get command
|
||
or al,sel_mask ;merge command and drive code
|
||
out fdc_com,al ;send command byte
|
||
parm_loop:
|
||
dec cl
|
||
jz exec_exit ;no (more) parameters, return
|
||
inc BX ;point to (next) parameter
|
||
parm_poll:
|
||
in al,fdc_stat
|
||
test al,20h ;"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 ;see if more parameters
|
||
|
||
flpy_poll_stat:
|
||
;--------------
|
||
; See if current operation complete
|
||
|
||
mov cx,cs:status_mask
|
||
in al,fdc_stat ;read status
|
||
and al,ch
|
||
xor al,cl ;isolate what we want to poll
|
||
mov al,0
|
||
jz flpy_poll_nrdy
|
||
mov al,0ffh
|
||
flpy_poll_nrdy:
|
||
ret
|
||
|
||
;=======
|
||
SECTRAN: ; Function 14: Sector Translate
|
||
;=======
|
||
; Translate sector number given a translate table
|
||
; If the translate table address is 0, don't translate
|
||
; input: CX = Sector Number
|
||
; DX = Offset of Translate Table
|
||
; output: AX = Translated Sector Number
|
||
|
||
cmp dx,0 ! jne sectran1
|
||
mov ax,cx ! ret
|
||
sectran1:
|
||
mov bx,cx
|
||
add bx,dx ;add sector to tran table addr
|
||
mov bl,[bx] ;get logical sector
|
||
xor bh,bh
|
||
mov ax,bx
|
||
ret
|
||
|
||
;=======
|
||
SETDMAB: ; Function 15: Set DMA Base
|
||
;=======
|
||
; set DMA segment
|
||
; input: CX = Segment of DMA buffer
|
||
; output: None
|
||
|
||
mov dma_seg,CX
|
||
ret
|
||
|
||
;========
|
||
flushbuf: ; Function 24: Flush Buffer
|
||
;========
|
||
; input: None
|
||
; output: AL = 00h if no error occurs
|
||
; = 01h if error occurs
|
||
; = 02h if read/only disk
|
||
|
||
xor al,al ;no need to flush buffer
|
||
ret ;with no blocking/deblocking
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* SUP/RTM CODE AREA
|
||
;*
|
||
;*****************************************************
|
||
;--------
|
||
rtm_poll: ;check dev, if not ready, do rtm poll
|
||
;--------
|
||
; Check poll condition.
|
||
; If not ready,Call MPM Poll Device Routine
|
||
; input: BX = device #
|
||
|
||
push bx ! mov cx,bx
|
||
call polldev ! pop bx
|
||
cmp al,0ffh ! je pllret
|
||
cmp stoppoll,true ! je rtm_poll
|
||
;---------
|
||
rtm_poll1: ; do poll_dev with no pretest
|
||
;---------
|
||
mov dx,bx ! mov cl,f_polldev
|
||
jmp supif
|
||
pllret: ret
|
||
|
||
;=======
|
||
polldev: ; Function 17: Poll Device
|
||
;=======
|
||
; input: CL = device number
|
||
; output: AL = 000h if not ready
|
||
; = 0ffh if ready
|
||
|
||
mov bh,0 ! mov bl,cl
|
||
shl bx,1
|
||
jmp polltbl[bx]
|
||
|
||
;=======
|
||
strtclk: ; Function 18: Start Clock
|
||
;=======
|
||
; Enable Flagsets on Tick Interrupts
|
||
; input: None
|
||
; output: None
|
||
|
||
mov clockon,true
|
||
ret
|
||
|
||
;=======
|
||
stopclk: ; Function 19: Stop Clock
|
||
;=======
|
||
; Disable Flagsets on Tick Interrupts
|
||
; input: None
|
||
; output: None
|
||
|
||
mov clockon,false
|
||
ret
|
||
|
||
;=======
|
||
getsegt: ; Function 16: Get Segment Table
|
||
;=======
|
||
; Not supported by MP/M-86
|
||
; input: None
|
||
; output: AX = 0ffffh
|
||
|
||
mov ax,0ffffh ! ret
|
||
|
||
;=========
|
||
selmemory: ; Function 22: Select Memory
|
||
;=========
|
||
; input: None
|
||
; output: None
|
||
|
||
ret
|
||
|
||
;====
|
||
idle: ; Function 23: Idle
|
||
;====
|
||
; input: None
|
||
; output: None
|
||
;
|
||
; The Idle routine is called by the Idle Process.
|
||
; Since the Idle routine has the worst priority (255)
|
||
; in the system, It will run only when nothing else
|
||
; can run. This routine cannot use any resources that
|
||
; may take it off the Ready List. This includes any
|
||
; kind of I/O that uses Poll Device or System Flags.
|
||
|
||
mov cl,f_dispatch
|
||
call supif
|
||
jmp idle
|
||
|
||
; If all devices are Interrupt Driven then the Idle
|
||
; Routine can be the following instead:
|
||
; halt ! jmp idle
|
||
; This cannot be used if any I/O uses POLL DEVICE
|
||
; since polling is only done during dispatches.
|
||
|
||
;=====
|
||
patch:
|
||
;=====
|
||
|
||
nop ! nop ! nop ! nop ! nop ! nop
|
||
nop ! nop ! nop ! nop ! nop ! nop
|
||
nop ! nop ! nop ! nop ! nop ! nop
|
||
nop ! nop ! nop ! nop ! nop ! nop
|
||
nop ! nop ! nop ! nop ! nop ! nop
|
||
nop ! nop
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* SYSTEM DATA AREA
|
||
;*
|
||
;*****************************************************
|
||
|
||
endcode rw 0
|
||
|
||
DSEG
|
||
org (offset endcode + 1) and 0fffeh
|
||
;org to an even word offset
|
||
;current UDA for MPM calls
|
||
udaseg rw 1
|
||
|
||
;-----------------------------------------------------
|
||
; XIOS FUNCTION TABLE
|
||
;-----------------------------------------------------
|
||
functab dw const ; 0-console status
|
||
dw conin ; 1-console input
|
||
dw conout ; 2-console output
|
||
dw plist ; 3-list output
|
||
dw punch ; 4-punch output
|
||
dw reader ; 5-reader input
|
||
dw HOME ; 6-home
|
||
dw SELDSK ; 7-select disk
|
||
dw SETTRK ; 8-set track
|
||
dw SETSEC ; 9-set sector
|
||
dw SETDMA ;10-set DMA offset
|
||
dw READ ;11-read
|
||
dw WRITE ;12-write
|
||
dw listst ;13-list status
|
||
dw sectran ;14-sector translate
|
||
dw setdmab ;15-set DMA base
|
||
dw getsegt ;16-get segment table
|
||
dw polldev ;17-poll device
|
||
dw strtclk ;18-start clock
|
||
dw stopclk ;19-stop clock
|
||
dw maxconsole ;20-maximum consoles
|
||
dw maxlist ;21-max list devices
|
||
dw selmemory ;22-select memory
|
||
dw idle ;23-idle
|
||
dw flushbuf ;24-flush buffer
|
||
|
||
;-----------------------------------------------------
|
||
;
|
||
; routines to find device status
|
||
; on poll device calls
|
||
;
|
||
polltbl dw const ;00-con 0 in
|
||
dw const ;01-con 1 in
|
||
dw const ;02-con 2 in
|
||
dw const ;03-con 3 in
|
||
dw const ;04-con 0 out
|
||
dw const ;05-con 1 out
|
||
dw const ;06-con 2 out
|
||
dw const ;07-con 3 out
|
||
dw plstst ;08-list 0 out
|
||
dw flpy_poll_stat ;09-dsk status
|
||
|
||
signon db cr,lf
|
||
db 'MP/M-86 V2.0 for SBC 8612',cr,lf,0
|
||
|
||
int_trp db ' Uninitialized Interrupt',cr,lf,0
|
||
|
||
loc_stk rw 32 ;local stack for initialization
|
||
stkbase equ offset $
|
||
tickint_tos rw 0
|
||
|
||
initss rw 1
|
||
initsp rw 1
|
||
rw 32
|
||
initstack rw 0
|
||
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* CHARACTER I/O DATA AREA
|
||
;*
|
||
;*****************************************************
|
||
;
|
||
org ((offset $) + 1) and 0fffeh
|
||
;
|
||
; console i/o table for
|
||
; status mask and port address
|
||
;
|
||
consttbl dw (c0inmsk shl 8) or c0stport
|
||
dw (c1inmsk shl 8) or c1stport
|
||
dw (c2inmsk shl 8) or c2stport
|
||
dw (c3inmsk shl 8) or c3stport
|
||
dw (c0outmsk shl 8) or c0stport
|
||
dw (c1outmsk shl 8) or c1stport
|
||
dw (c2outmsk shl 8) or c2stport
|
||
dw (c3outmsk shl 8) or c3stport
|
||
;
|
||
; console input table for
|
||
; poll device no. and port address
|
||
;
|
||
conintbl dw (c0indev shl 8) or c0ioport
|
||
dw (c1indev shl 8) or c1ioport
|
||
dw (c2indev shl 8) or c2ioport
|
||
dw (c3indev shl 8) or c3ioport
|
||
;
|
||
; console output table for
|
||
; poll device no. and port address
|
||
;
|
||
conouttbl dw (c0outdev shl 8) or c0ioport
|
||
dw (c1outdev shl 8) or c1ioport
|
||
dw (c2outdev shl 8) or c2ioport
|
||
dw (c3outdev shl 8) or c3ioport
|
||
;
|
||
; list i/o table for
|
||
; status mask and port address
|
||
;
|
||
loutsttbl dw (l0outmsk shl 8) or l0stport
|
||
;
|
||
; list output for
|
||
; poll device no. and port address
|
||
;
|
||
louttbl dw (l0outdev shl 8) or l0ioport
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* DISK DATA AREA
|
||
;*
|
||
;*****************************************************
|
||
|
||
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,'Null Error ??',0
|
||
er1 equ er0
|
||
er2 equ er0
|
||
er3 equ er0
|
||
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,'Trk 00 Not Found :',0
|
||
erB db cr,lf,'Write Fault :',0
|
||
erC db cr,lf,'Sector Not Found :',0
|
||
erD equ er0
|
||
erE equ er0
|
||
erF equ er0
|
||
nrdymsg equ er8
|
||
|
||
rtry_cnt db 0 ;disk error retry counter
|
||
last_com dw 0 ;address of last command string
|
||
dma_adr dw 0 ;dma offset stored here
|
||
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
|
||
rd_wr db 0 ;read/write function code
|
||
trk db 0 ;track #
|
||
sect db 0 ;sector #
|
||
|
||
hom_com db 2,29h,0 ;home drive command
|
||
rds_com db 1,2ch ;read status command
|
||
|
||
status_mask dw 0 ;mask for flpy_poll
|
||
|
||
|
||
disk db 0 ;physical disk selected
|
||
|
||
; logical to physical disk
|
||
; translation table
|
||
; A B C D
|
||
dtrntbl db 000h,001h,0ffh,0ffh
|
||
; E F G H
|
||
db 0ffh,0ffh,0ffh,0ffh
|
||
; I J K L
|
||
db 0ffh,0ffh,0ffh,0ffh
|
||
; M N O P
|
||
;*****MDISK SUPPORT*****
|
||
if memdisk
|
||
db 002h,0ffh,0ffh,0ffh
|
||
endif
|
||
;***********************
|
||
if not memdisk
|
||
db 0ffh,0ffh,0ffh,0ffh
|
||
endif
|
||
|
||
; disk home routine table
|
||
dskhomtbl dw flpy_home ;A drive
|
||
dw flpy_home ;B drive
|
||
;*****MDISK SUPPORT*****
|
||
if memdisk
|
||
dw hom_ret ;M drive
|
||
endif
|
||
;***********************
|
||
|
||
; disk read routine table
|
||
dskrdtbl dw flpy_read ;A drive
|
||
dw flpy_read ;B drive
|
||
;*****MDISK SUPPORT*****
|
||
if memdisk
|
||
dw mdsk_read ;M drive
|
||
endif
|
||
;***********************
|
||
|
||
; disk write routine table
|
||
dskwrttbl dw flpy_write ;A drive
|
||
dw flpy_write ;B drive
|
||
;*****MDISK SUPPORT*****
|
||
if memdisk
|
||
dw mdsk_write ;M drive
|
||
endif
|
||
;***********************
|
||
|
||
include singles.lib ;read in disk definitions
|
||
|
||
;*****************************************************
|
||
;*
|
||
;* SUP/RTM DATA AREA
|
||
;*
|
||
;*****************************************************
|
||
stoppoll dw false ;disallows poll_device
|
||
;for internal printing
|
||
;of strings when true
|
||
|
||
clockon db false ;if true, Tick flag is
|
||
;set on Tick interrupts
|
||
|
||
tick_count db 60
|
||
;
|
||
; scratch area
|
||
;
|
||
dw 0cccch,0cccch,0cccch
|
||
dw 0cccch,0cccch,0cccch
|
||
dw 0cccch,0cccch,0cccch
|
||
dw 0cccch,0cccch,0cccch
|
||
dw 0cccch,0cccch,0cccch
|
||
dw 0cccch,0cccch,0cccch
|
||
dw 0cccch,0cccch,0cccch
|
||
|
||
db 0 ;fill last address for GENCMD
|
||
|
||
|