mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 00:14:25 +00:00
Upload
Digital Research
This commit is contained in:
658
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/8087.LIB
Normal file
658
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/8087.LIB
Normal file
@@ -0,0 +1,658 @@
|
||||
nolist
|
||||
|
||||
; *****************************
|
||||
; * Codemacros for 8087 *
|
||||
; * numeric data processor: *
|
||||
; ***************************
|
||||
;
|
||||
; stack references:
|
||||
st equ 0 ; stack top (= register 0)
|
||||
st0 equ 0 ; register 0
|
||||
st1 equ 1 ; register 1
|
||||
st2 equ 2 ; register 2
|
||||
st3 equ 3 ; register 3
|
||||
st4 equ 4 ; register 4
|
||||
st5 equ 5 ; register 5
|
||||
st6 equ 6 ; register 6
|
||||
st7 equ 7 ; register 7
|
||||
;
|
||||
;
|
||||
codemacro FLD src:Mb
|
||||
segfix src
|
||||
db 0d9h
|
||||
modrm 0,src
|
||||
endm
|
||||
|
||||
codemacro FLD src:Mw
|
||||
segfix src
|
||||
db 0ddh
|
||||
modrm 0,src
|
||||
endm
|
||||
|
||||
codemacro FLD src:Db(0,7)
|
||||
db 0d9h
|
||||
dbit 5(18h),3(src(0))
|
||||
endm
|
||||
|
||||
codemacro FLDTR src:M
|
||||
segfix src
|
||||
db 0dbh
|
||||
modrm 5,src
|
||||
endm
|
||||
|
||||
codemacro FST dst:Mb
|
||||
segfix dst
|
||||
db 0d9h
|
||||
modrm 2,dst
|
||||
endm
|
||||
|
||||
codemacro FST dst:Mw
|
||||
segfix dst
|
||||
db 0ddh
|
||||
modrm 2,dst
|
||||
endm
|
||||
|
||||
codemacro FST dst:Db(0,7)
|
||||
db 0ddh
|
||||
dbit 5(1ah),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FSTP dst:Mb
|
||||
segfix dst
|
||||
db 0d9h
|
||||
modrm 3,dst
|
||||
endm
|
||||
|
||||
codemacro FSTP dst:Mw
|
||||
segfix dst
|
||||
db 0ddh
|
||||
modrm 3,dst
|
||||
endm
|
||||
|
||||
codemacro FSTP dst:Db(0,7)
|
||||
db 0ddh
|
||||
dbit 5(1bh),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FSTPTR dst:M
|
||||
segfix dst
|
||||
db 0dbh
|
||||
modrm 7,dst
|
||||
endm
|
||||
|
||||
codemacro FXCH
|
||||
dw 0c9d9h
|
||||
endm
|
||||
|
||||
codemacro FXCH dst:Db(0,7)
|
||||
db 0d9h
|
||||
dbit 5(19h),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FILD src:Mb
|
||||
segfix src
|
||||
db 0dbh
|
||||
modrm 0,src
|
||||
endm
|
||||
|
||||
codemacro FILDLI src:Mw
|
||||
segfix src
|
||||
db 0dfh
|
||||
modrm 5,src
|
||||
endm
|
||||
|
||||
codemacro FILD src:Mw
|
||||
segfix src
|
||||
db 0dfh
|
||||
modrm 0,src
|
||||
endm
|
||||
|
||||
codemacro FIST dst:Mb
|
||||
segfix dst
|
||||
db 0dbh
|
||||
modrm 2,dst
|
||||
endm
|
||||
|
||||
codemacro FIST dst:Mw
|
||||
segfix dst
|
||||
db 0dfh
|
||||
modrm 2,dst
|
||||
endm
|
||||
|
||||
codemacro FISTP dst:Mb
|
||||
segfix dst
|
||||
db 0dbh
|
||||
modrm 3,dst
|
||||
endm
|
||||
|
||||
codemacro FISTPLI dst:Mw
|
||||
segfix dst
|
||||
db 0dfh
|
||||
modrm 7,dst
|
||||
endm
|
||||
|
||||
codemacro FISTP dst:Mw
|
||||
segfix dst
|
||||
db 0dfh
|
||||
modrm 3,dst
|
||||
endm
|
||||
|
||||
codemacro FBLD src:Mb
|
||||
segfix src
|
||||
db 0dfh
|
||||
modrm 4,src
|
||||
endm
|
||||
|
||||
codemacro FBSTP dst:Mb
|
||||
segfix dst
|
||||
db 0dfh
|
||||
modrm 6,dst
|
||||
endm
|
||||
|
||||
codemacro FADD
|
||||
dw 0c1d8h
|
||||
endm
|
||||
|
||||
codemacro FADD dst:Db(0),src:Db(0,7)
|
||||
db 0d8h
|
||||
dbit 5(18h),3(src(0))
|
||||
endm
|
||||
|
||||
codemacro FADD src:Mb
|
||||
segfix src
|
||||
db 0d8h
|
||||
modrm 0,src
|
||||
endm
|
||||
|
||||
codemacro FADD src:Mw
|
||||
segfix src
|
||||
db 0dch
|
||||
modrm 0,src
|
||||
endm
|
||||
|
||||
codemacro FADD dst:Db(0,7),src:Db(0)
|
||||
db 0dch
|
||||
dbit 5(18h),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FADDP dst:Db(0,7),src:Db(0)
|
||||
db 0deh
|
||||
dbit 5(18h),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FIADD src:Mb
|
||||
segfix src
|
||||
db 0dah
|
||||
modrm 0,src
|
||||
endm
|
||||
|
||||
codemacro FIADD src:Mw
|
||||
segfix src
|
||||
db 0deh
|
||||
modrm 0,src
|
||||
endm
|
||||
|
||||
codemacro FSUB
|
||||
dw 0e1d8h
|
||||
endm
|
||||
|
||||
codemacro FSUB dst:Db(0),src:Db(0,7)
|
||||
db 0d8h
|
||||
dbit 5(1ch),3(src(0))
|
||||
endm
|
||||
|
||||
codemacro FSUB src:Mb
|
||||
segfix src
|
||||
db 0d8h
|
||||
modrm 4,src
|
||||
endm
|
||||
|
||||
codemacro FSUB src:Mw
|
||||
segfix src
|
||||
db 0dch
|
||||
modrm 4,src
|
||||
endm
|
||||
|
||||
codemacro FSUB dst:Db(0,7),src:Db(0)
|
||||
db 0dch
|
||||
dbit 5(1ch),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FSUBP dst:Db(0,7),src:Db(0)
|
||||
db 0deh
|
||||
dbit 5(1ch),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FISUB src:Mb
|
||||
segfix src
|
||||
db 0dah
|
||||
modrm 4,src
|
||||
endm
|
||||
|
||||
codemacro FISUB src:Mw
|
||||
segfix src
|
||||
db 0deh
|
||||
modrm 4,src
|
||||
endm
|
||||
|
||||
codemacro FSUBR
|
||||
dw 0e9d8h
|
||||
endm
|
||||
|
||||
codemacro FSUBR dst:Db(0),src:Db(0,7)
|
||||
db 0d8h
|
||||
dbit 5(1dh),3(src(0))
|
||||
endm
|
||||
|
||||
codemacro FSUBR src:Mb
|
||||
segfix src
|
||||
db 0d8h
|
||||
modrm 5,src
|
||||
endm
|
||||
|
||||
codemacro FSUBR src:Mw
|
||||
segfix src
|
||||
db 0dch
|
||||
modrm 5,src
|
||||
endm
|
||||
|
||||
codemacro FSUBR dst:Db(0,7),src:Db(0)
|
||||
db 0dch
|
||||
dbit 5(1dh),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FSUBRP dst:Db(0,7),src:Db(0)
|
||||
db 0deh
|
||||
dbit 5(1dh),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FISUBR src:Mb
|
||||
segfix src
|
||||
db 0dah
|
||||
modrm 5,src
|
||||
endm
|
||||
|
||||
codemacro FISUBR src:Mw
|
||||
segfix src
|
||||
db 0deh
|
||||
modrm 5,src
|
||||
endm
|
||||
|
||||
codemacro FMUL
|
||||
dw 0c9d8h
|
||||
endm
|
||||
|
||||
codemacro FMUL dst:Db(0),src:Db(0,7)
|
||||
db 0d8h
|
||||
dbit 5(19h),3(src(0))
|
||||
endm
|
||||
|
||||
codemacro FMUL src:Mb
|
||||
segfix src
|
||||
db 0d8h
|
||||
modrm 1,src
|
||||
endm
|
||||
|
||||
codemacro FMUL src:Mw
|
||||
segfix src
|
||||
db 0dch
|
||||
modrm 1,src
|
||||
endm
|
||||
|
||||
codemacro FMUL dst:Db(0,7),src:Db(0)
|
||||
db 0dch
|
||||
dbit 5(19h),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FMULP dst:Db(0,7),src:Db(0)
|
||||
db 0deh
|
||||
dbit 5(19h),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FIMUL src:Mb
|
||||
segfix src
|
||||
db 0dah
|
||||
modrm 1,src
|
||||
endm
|
||||
|
||||
codemacro FIMUL src:Mw
|
||||
segfix src
|
||||
db 0deh
|
||||
modrm 1,src
|
||||
endm
|
||||
|
||||
codemacro FDIV
|
||||
dw 0f1d8h
|
||||
endm
|
||||
|
||||
codemacro FDIV dst:Db(0),src:Db(0,7)
|
||||
db 0d8h
|
||||
dbit 5(1eh),3(src(0))
|
||||
endm
|
||||
|
||||
codemacro FDIV src:Mb
|
||||
segfix src
|
||||
db 0d8h
|
||||
modrm 6,src
|
||||
endm
|
||||
|
||||
codemacro FDIV src:Mw
|
||||
segfix src
|
||||
db 0dch
|
||||
modrm 6,src
|
||||
endm
|
||||
|
||||
codemacro FDIV dst:Db(0,7),src:Db(0)
|
||||
db 0dch
|
||||
dbit 5(1eh),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FDIVP dst:Db(0,7),src:Db(0)
|
||||
db 0deh
|
||||
dbit 5(1eh),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FIDIV src:Mb
|
||||
segfix src
|
||||
db 0dah
|
||||
modrm 6,src
|
||||
endm
|
||||
|
||||
codemacro FIDIV src:Mw
|
||||
segfix src
|
||||
db 0deh
|
||||
modrm 6,src
|
||||
endm
|
||||
|
||||
codemacro FDIVR
|
||||
dw 0f9d8h
|
||||
endm
|
||||
|
||||
codemacro FDIVR dst:Db(0),src:Db(0,7)
|
||||
db 0d8h
|
||||
dbit 5(1fh),3(src(0))
|
||||
endm
|
||||
|
||||
codemacro FDIVR src:Mb
|
||||
segfix src
|
||||
db 0d8h
|
||||
modrm 7,src
|
||||
endm
|
||||
|
||||
codemacro FDIVR src:Mw
|
||||
segfix src
|
||||
db 0dch
|
||||
modrm 7,src
|
||||
endm
|
||||
|
||||
codemacro FDIVR dst:Db(0,7),src:Db(0)
|
||||
db 0dch
|
||||
dbit 5(1fh),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FDIVRP dst:Db(0,7),src:Db(0)
|
||||
db 0deh
|
||||
dbit 5(1fh),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FIDIVR src:Mb
|
||||
segfix src
|
||||
db 0dah
|
||||
modrm 7,src
|
||||
endm
|
||||
|
||||
codemacro FIDIVR src:Mw
|
||||
segfix src
|
||||
db 0deh
|
||||
modrm 7,src
|
||||
endm
|
||||
|
||||
codemacro FSQRT
|
||||
dw 0fad9h
|
||||
endm
|
||||
|
||||
codemacro FSCALE
|
||||
dw 0fdd9h
|
||||
endm
|
||||
|
||||
codemacro FPREM
|
||||
dw 0f8d9h
|
||||
endm
|
||||
|
||||
codemacro FRNDINT
|
||||
dw 0fcd9h
|
||||
endm
|
||||
|
||||
codemacro FXTRACT
|
||||
dw 0f4d9h
|
||||
endm
|
||||
|
||||
codemacro FABS
|
||||
dw 0e1d9h
|
||||
endm
|
||||
|
||||
codemacro FCHS
|
||||
dw 0e0d9h
|
||||
endm
|
||||
|
||||
codemacro FCOM
|
||||
dw 0d1d8h
|
||||
endm
|
||||
|
||||
codemacro FCOM src:Db(0,7)
|
||||
db 0d8h
|
||||
dbit 5(1ah),3(src(0))
|
||||
endm
|
||||
|
||||
codemacro FCOM src:Mb
|
||||
segfix src
|
||||
db 0d8h
|
||||
modrm 2,src
|
||||
endm
|
||||
|
||||
codemacro FCOM src:Mw
|
||||
segfix src
|
||||
db 0dch
|
||||
modrm 2,src
|
||||
endm
|
||||
|
||||
codemacro FCOMP
|
||||
dw 0d9d8h
|
||||
endm
|
||||
|
||||
codemacro FCOMP src:Db(0,7)
|
||||
db 0d8h
|
||||
dbit 5(1bh),3(src(0))
|
||||
endm
|
||||
|
||||
codemacro FCOMP src:Mb
|
||||
segfix src
|
||||
db 0d8h
|
||||
modrm 3,src
|
||||
endm
|
||||
|
||||
codemacro FCOMP src:Mw
|
||||
segfix src
|
||||
db 0dch
|
||||
modrm 3,src
|
||||
endm
|
||||
|
||||
codemacro FCOMPP
|
||||
dw 0c9deh
|
||||
endm
|
||||
|
||||
codemacro FICOM src:Mb
|
||||
segfix src
|
||||
db 0dah
|
||||
modrm 2,src
|
||||
endm
|
||||
|
||||
codemacro FICOM src:Mw
|
||||
segfix src
|
||||
db 0deh
|
||||
modrm 2,src
|
||||
endm
|
||||
|
||||
codemacro FICOMP src:Mb
|
||||
segfix src
|
||||
db 0dah
|
||||
modrm 3,src
|
||||
endm
|
||||
|
||||
codemacro FICOMP src:Mw
|
||||
segfix src
|
||||
db 0deh
|
||||
modrm 3,src
|
||||
endm
|
||||
|
||||
codemacro FTST
|
||||
dw 0e4d9h
|
||||
endm
|
||||
|
||||
codemacro FXAM
|
||||
dw 0e5d9h
|
||||
endm
|
||||
|
||||
codemacro FPTAN
|
||||
dw 0f2d9h
|
||||
endm
|
||||
|
||||
codemacro FPATAN
|
||||
dw 0f3d9h
|
||||
endm
|
||||
|
||||
codemacro F2XM1
|
||||
dw 0f0d9h
|
||||
endm
|
||||
|
||||
codemacro FYL2X
|
||||
dw 0f1d9h
|
||||
endm
|
||||
|
||||
codemacro FYL2XP1
|
||||
dw 0f9d9h
|
||||
endm
|
||||
|
||||
codemacro FLDZ
|
||||
dw 0eed9h
|
||||
endm
|
||||
|
||||
codemacro FLD1
|
||||
dw 0e8d9h
|
||||
endm
|
||||
|
||||
codemacro FLDPI
|
||||
dw 0ebd9h
|
||||
endm
|
||||
|
||||
codemacro FLDL2T
|
||||
dw 0e9d9h
|
||||
endm
|
||||
|
||||
codemacro FLDL2E
|
||||
dw 0ead9h
|
||||
endm
|
||||
|
||||
codemacro FLDLG2
|
||||
dw 0ecd9h
|
||||
endm
|
||||
|
||||
codemacro FLDLN2
|
||||
dw 0edd9h
|
||||
endm
|
||||
|
||||
codemacro FINIT
|
||||
dw 0e3dbh
|
||||
endm
|
||||
|
||||
FNINIT equ FINIT
|
||||
|
||||
codemacro FDISI
|
||||
dw 0e1dbh
|
||||
endm
|
||||
|
||||
FNDISI equ FDISI
|
||||
|
||||
codemacro FENI
|
||||
dw 0e0dbh
|
||||
endm
|
||||
|
||||
FNENI equ FENI
|
||||
|
||||
codemacro FLDCW src:Mw
|
||||
segfix src
|
||||
db 0d9h
|
||||
modrm 5,src
|
||||
endm
|
||||
|
||||
codemacro FSTCW dst:Mw
|
||||
segfix dst
|
||||
db 0d9h
|
||||
modrm 7,dst
|
||||
endm
|
||||
|
||||
FNSTCW equ FSTCW
|
||||
|
||||
codemacro FSTSW dst:Mw
|
||||
segfix dst
|
||||
db 0ddh
|
||||
modrm 7,dst
|
||||
endm
|
||||
|
||||
FNSTSW equ FSTSW
|
||||
|
||||
codemacro FCLEX
|
||||
dw 0e2dbh
|
||||
endm
|
||||
|
||||
FNCLEX equ FCLEX
|
||||
|
||||
codemacro FSAVE dst:M
|
||||
segfix dst
|
||||
db 0ddh
|
||||
modrm 6,dst
|
||||
endm
|
||||
|
||||
FNSAVE equ FSAVE
|
||||
|
||||
codemacro FRSTOR src:M
|
||||
segfix src
|
||||
db 0ddh
|
||||
modrm 4,src
|
||||
endm
|
||||
|
||||
codemacro FSTENV dst:M
|
||||
segfix dst
|
||||
db 0d9h
|
||||
modrm 6,dst
|
||||
endm
|
||||
|
||||
FNSTENV equ FSTENV
|
||||
|
||||
codemacro FLDENV src:M
|
||||
segfix src
|
||||
db 0d9h
|
||||
modrm 4,src
|
||||
endm
|
||||
|
||||
codemacro FINCSTP
|
||||
dw 0f7d9h
|
||||
endm
|
||||
|
||||
codemacro FDECSTP
|
||||
dw 0f6d9h
|
||||
endm
|
||||
|
||||
codemacro FFREE dst:Db(0,7)
|
||||
db 0ddh
|
||||
dbit 5(18h),3(dst(0))
|
||||
endm
|
||||
|
||||
codemacro FNOP
|
||||
dw 0d0ddh
|
||||
endm
|
||||
|
||||
FWAIT equ WAIT
|
||||
|
||||
list
|
||||
|
BIN
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/ASM86.CMD
Normal file
BIN
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/ASM86.CMD
Normal file
Binary file not shown.
BIN
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/ASM86.COM
Normal file
BIN
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/ASM86.COM
Normal file
Binary file not shown.
690
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/BIOS.A86
Normal file
690
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/BIOS.A86
Normal file
@@ -0,0 +1,690 @@
|
||||
title '8086 Disk I/O Drivers'
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* Basic Input/Output System (BIOS) for *
|
||||
;* CP/M-86 Configured for iSBC 86/12 with *
|
||||
;* the iSBC 204 Floppy Disk Controller *
|
||||
;* *
|
||||
;* (Note: this file contains both embedded *
|
||||
;* tabs and blanks to minimize the list file *
|
||||
;* width for printing purposes. You may wish*
|
||||
;* to expand the blanks before performing *
|
||||
;* major editing.) *
|
||||
;*********************************************
|
||||
|
||||
; 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
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* Loader_bios is true if assembling the *
|
||||
;* LOADER BIOS, otherwise BIOS is for the *
|
||||
;* CPM.SYS file. Blc_list is true if we *
|
||||
;* have a serial printer attached to BLC8538 *
|
||||
;* Bdos_int is interrupt used for earlier *
|
||||
;* versions. *
|
||||
;* *
|
||||
;*********************************************
|
||||
|
||||
loader_bios equ false
|
||||
blc_list equ true
|
||||
bdos_int equ 224 ;reserved BDOS Interrupt
|
||||
|
||||
IF not loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
bios_code equ 2500h
|
||||
ccp_offset equ 0000h
|
||||
bdos_ofst equ 0B06h ;BDOS entry point
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;not loader_bios
|
||||
|
||||
IF loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
bios_code equ 1200h ;start of LDBIOS
|
||||
ccp_offset equ 0003h ;base of CPMLOADER
|
||||
bdos_ofst equ 0406h ;stripped BDOS entry
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;loader_bios
|
||||
|
||||
csts equ 0DAh ;i8251 status port
|
||||
cdata equ 0D8h ; " data port
|
||||
|
||||
IF blc_list
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
lsts equ 41h ;2651 No. 0 on BLC8538 status port
|
||||
ldata equ 40h ; " " " " " data port
|
||||
blc_reset equ 60h ;reset selected USARTS on BLC8538
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;blc_list
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* 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)
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* INIT Entry Point, Differs for LDBIOS and *
|
||||
;* BIOS, according to "Loader_Bios" value *
|
||||
;* *
|
||||
;*********************************************
|
||||
|
||||
INIT: ;print signon message and initialize hardware
|
||||
mov ax,cs ;we entered with a JMPF so use
|
||||
mov ss,ax ; CS: as the initial value of SS:,
|
||||
mov ds,ax ; DS:,
|
||||
mov es,ax ; and ES:
|
||||
;use local stack during initialization
|
||||
mov sp,offset stkbase
|
||||
cld ;set forward direction
|
||||
|
||||
IF not loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
; This is a BIOS for the CPM.SYS file.
|
||||
; Setup all interrupt vectors in low
|
||||
; memory to address trap
|
||||
|
||||
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
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* National "BLC 8538" Channel 0 for a serial*
|
||||
;* 9600 baud printer - this board uses 8 Sig-*
|
||||
;* netics 2651 Usarts which have on-chip baud*
|
||||
;* rate generators. *
|
||||
;* *
|
||||
;*********************************************
|
||||
|
||||
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
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;not loader_bios
|
||||
|
||||
IF loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
;This is a BIOS for the LOADER
|
||||
push ds ;save data segment
|
||||
mov ax,0
|
||||
mov ds,ax ;point to segment zero
|
||||
;BDOS interrupt offset
|
||||
mov bdos_offset,bdos_ofst
|
||||
mov bdos_segment,CS ;bdos interrupt segment
|
||||
pop ds ;restore data segment
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;loader_bios
|
||||
|
||||
mov bx,offset signon
|
||||
call pmsg ;print signon message
|
||||
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
|
||||
|
||||
IF not loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
int_trap:
|
||||
cli ;block interrupts
|
||||
mov ax,cs
|
||||
mov ds,ax ;get our data segment
|
||||
mov bx,offset int_trp
|
||||
call pmsg
|
||||
hlt ;hardstop
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;not loader_bios
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* 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
|
||||
|
||||
IF blc_list
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
call LISTST
|
||||
jz LISTOUT ;wait for printer not busy
|
||||
mov al,cl
|
||||
out ldata,al ;send char to TI 810
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;blc_list
|
||||
|
||||
ret
|
||||
|
||||
LISTST: ;poll list status
|
||||
|
||||
IF blc_list
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
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
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;blc_list
|
||||
|
||||
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 bx,0000h
|
||||
cmp cl,2 ;this BIOS only supports 2 disks
|
||||
jnb return ;return w/ 0000 in BX if bad drive
|
||||
mov al, 80h
|
||||
cmp cl,0
|
||||
jne sel1 ;drive 1 if not zero
|
||||
mov al, 40h ;else drive is 0
|
||||
sel1: mov sel_mask,al ;save drive select mask
|
||||
;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
|
||||
;create offset from Disk Parameter Base
|
||||
add bx,offset dp_base
|
||||
return:
|
||||
ret
|
||||
|
||||
HOME: ;move selected disk to home position (Track 0)
|
||||
mov trk,0 ;set disk i/o to track zero
|
||||
mov bx,offset hom_com
|
||||
call execute
|
||||
jz return ;home drive and return if OK
|
||||
mov bx,offset bad_hom ;else print
|
||||
call pmsg ;"Home Error"
|
||||
jmps home ;and retry
|
||||
|
||||
SETTRK: ;set track address given by CX
|
||||
mov trk,cl ;we only use 8 bits of track address
|
||||
ret
|
||||
|
||||
SETSEC: ;set sector number given by cx
|
||||
mov sect,cl ;we only use 8 bits of sector address
|
||||
ret
|
||||
|
||||
SECTRAN: ;translate sector CX using table at [DX]
|
||||
mov bx,cx
|
||||
add bx,dx ;add sector to tran table address
|
||||
mov bl,[bx] ;get logical sector
|
||||
ret
|
||||
|
||||
SETDMA: ;set DMA offset given by CX
|
||||
mov dma_adr,CX
|
||||
ret
|
||||
|
||||
SETDMAB: ;set DMA segment given by CX
|
||||
mov dma_seg,CX
|
||||
ret
|
||||
;
|
||||
GETSEGT: ;return address of physical memory table
|
||||
mov bx,offset seg_table
|
||||
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:
|
||||
mov al,12h ;basic read sector command
|
||||
jmps r_w_common
|
||||
|
||||
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 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
|
||||
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
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* 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,12h
|
||||
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,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 segment address
|
||||
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 ;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
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* Data Areas *
|
||||
;* *
|
||||
;*********************************************
|
||||
data_offset equ offset $
|
||||
|
||||
dseg
|
||||
org data_offset ;contiguous with code segment
|
||||
|
||||
IF loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
signon db cr,lf,cr,lf
|
||||
db 'CP/M-86 Version 2.2',cr,lf,0
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;loader_bios
|
||||
|
||||
IF not loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
signon db cr,lf,cr,lf
|
||||
db ' System Generated - 11 Jan 81',cr,lf,0
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;not loader_bios
|
||||
|
||||
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,'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
|
||||
|
||||
; 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 2000h ;second is 20000 -
|
||||
dw 2000h ;3FFFF (128k)
|
||||
|
||||
include singles.lib ;read in disk definitions
|
||||
|
||||
loc_stk rw 32 ;local stack for initialization
|
||||
stkbase equ offset $
|
||||
|
||||
lastoff equ offset $
|
||||
tpa_seg equ (lastoff+0400h+15) / 16
|
||||
tpa_len equ 0800h - tpa_seg
|
||||
db 0 ;fill last address for GENCMD
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* Dummy Data Section *
|
||||
;* *
|
||||
;*********************************************
|
||||
dseg 0 ;absolute low memory
|
||||
org 0 ;(interrupt vectors)
|
||||
int0_offset rw 1
|
||||
int0_segment rw 1
|
||||
; pad to system call vector
|
||||
rw 2*(bdos_int-1)
|
||||
|
||||
bdos_offset rw 1
|
||||
bdos_segment rw 1
|
||||
END
|
||||
|
367
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/CBIOS.A86
Normal file
367
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/CBIOS.A86
Normal file
@@ -0,0 +1,367 @@
|
||||
title 'Customized Basic I/O System'
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* This Customized BIOS adapts CP/M-86 to *
|
||||
;* the following hardware configuration *
|
||||
;* Processor: *
|
||||
;* Brand: *
|
||||
;* Controller: *
|
||||
;* *
|
||||
;* *
|
||||
;* Programmer: *
|
||||
;* Revisions : *
|
||||
;* *
|
||||
;*********************************************
|
||||
|
||||
true equ -1
|
||||
false equ not true
|
||||
cr equ 0dh ;carriage return
|
||||
lf equ 0ah ;line feed
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* Loader_bios is true if assembling the *
|
||||
;* LOADER BIOS, otherwise BIOS is for the *
|
||||
;* CPM.SYS file. *
|
||||
;* *
|
||||
;*********************************************
|
||||
|
||||
loader_bios equ false
|
||||
bdos_int equ 224 ;reserved BDOS interrupt
|
||||
|
||||
IF not loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
bios_code equ 2500h
|
||||
ccp_offset equ 0000h
|
||||
bdos_ofst equ 0B06h ;BDOS entry point
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;not loader_bios
|
||||
|
||||
IF loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
bios_code equ 1200h ;start of LDBIOS
|
||||
ccp_offset equ 0003h ;base of CPMLOADER
|
||||
bdos_ofst equ 0406h ;stripped BDOS entry
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;loader_bios
|
||||
|
||||
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)
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* INIT Entry Point, Differs for LDBIOS and *
|
||||
;* BIOS, according to "Loader_Bios" value *
|
||||
;* *
|
||||
;*********************************************
|
||||
|
||||
INIT: ;print signon message and initialize hardware
|
||||
mov ax,cs ;we entered with a JMPF so use
|
||||
mov ss,ax ;CS: as the initial value of SS:,
|
||||
mov ds,ax ;DS:,
|
||||
mov es,ax ;and ES:
|
||||
;use local stack during initialization
|
||||
mov sp,offset stkbase
|
||||
cld ;set forward direction
|
||||
|
||||
IF not loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
; This is a BIOS for the CPM.SYS file.
|
||||
; Setup all interrupt vectors in low
|
||||
; memory to address trap
|
||||
|
||||
push ds ;save the DS register
|
||||
mov IOBYTE,0 ;clear IOBYTE
|
||||
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
|
||||
|
||||
; (additional CP/M-86 initialization)
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;not loader_bios
|
||||
|
||||
IF loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
;This is a BIOS for the LOADER
|
||||
push ds ;save data segment
|
||||
mov ax,0
|
||||
mov ds,ax ;point to segment zero
|
||||
;BDOS interrupt offset
|
||||
mov bdos_offset,bdos_ofst
|
||||
mov bdos_segment,CS ;bdos interrupt segment
|
||||
; (additional LOADER initialization)
|
||||
pop ds ;restore data segment
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;loader_bios
|
||||
|
||||
mov bx,offset signon
|
||||
call pmsg ;print signon message
|
||||
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
|
||||
|
||||
IF not loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
int_trap:
|
||||
cli ;block interrupts
|
||||
mov ax,cs
|
||||
mov ds,ax ;get our data segment
|
||||
mov bx,offset int_trp
|
||||
call pmsg
|
||||
hlt ;hardstop
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;not loader_bios
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* CP/M Character I/O Interface Routines *
|
||||
;* *
|
||||
;*********************************************
|
||||
|
||||
CONST: ;console status
|
||||
rs 10 ;(fill-in)
|
||||
ret
|
||||
|
||||
CONIN: ;console input
|
||||
call CONST
|
||||
jz CONIN ;wait for RDA
|
||||
rs 10 ;(fill-in)
|
||||
ret
|
||||
|
||||
CONOUT: ;console output
|
||||
rs 10 ;(fill-in)
|
||||
ret ;then return data
|
||||
|
||||
LISTOUT: ;list device output
|
||||
rs 10 ;(fill-in)
|
||||
ret
|
||||
|
||||
LISTST: ;poll list status
|
||||
rs 10 ;(fill-in)
|
||||
ret
|
||||
|
||||
PUNCH: ;write punch device
|
||||
rs 10 ;(fill-in)
|
||||
ret
|
||||
|
||||
READER:
|
||||
rs 10 ;(fill-in)
|
||||
ret
|
||||
|
||||
GETIOBF:
|
||||
mov al,IOBYTE
|
||||
ret
|
||||
|
||||
SETIOBF:
|
||||
mov IOBYTE,cl ;set iobyte
|
||||
ret ;iobyte not implemented
|
||||
|
||||
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
|
||||
ndisks equ 2 ;number of disks (up to 16)
|
||||
mov disk,cl ;save disk number
|
||||
mov bx,0000h ;ready for error return
|
||||
cmp cl,ndisks ;n beyond max disks?
|
||||
jnb return ;return if so
|
||||
mov ch,0 ;double(n)
|
||||
mov bx,cx ;bx = n
|
||||
mov cl,4 ;ready for *16
|
||||
shl bx,cl ;n = n * 16
|
||||
mov cx,offset dpbase
|
||||
add bx,cx ;dpbase + n * 16
|
||||
return: ret ;bx = .dph
|
||||
|
||||
HOME: ;move selected disk to home position (Track 0)
|
||||
mov trk,0 ;set disk i/o to track zero
|
||||
rs 10 ;(fill-in)
|
||||
ret
|
||||
|
||||
SETTRK: ;set track address given by CX
|
||||
mov trk,CX
|
||||
ret
|
||||
|
||||
SETSEC: ;set sector number given by cx
|
||||
mov sect,CX
|
||||
ret
|
||||
|
||||
SECTRAN: ;translate sector CX using table at [DX]
|
||||
mov bx,cx
|
||||
add bx,dx ;add sector to tran table address
|
||||
mov bl,[bx] ;get logical sector
|
||||
ret
|
||||
|
||||
SETDMA: ;set DMA offset given by CX
|
||||
mov dma_adr,CX
|
||||
ret
|
||||
|
||||
SETDMAB: ;set DMA segment given by CX
|
||||
mov dma_seg,CX
|
||||
ret
|
||||
;
|
||||
GETSEGT: ;return address of physical memory table
|
||||
mov bx,offset seg_table
|
||||
ret
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* All disk I/O parameters are setup: *
|
||||
;* DISK is disk number (SELDSK) *
|
||||
;* TRK is track number (SETTRK) *
|
||||
;* SECT is sector number (SETSEC) *
|
||||
;* DMA_ADR is the DMA offset (SETDMA) *
|
||||
;* DMA_SEG is the DMA segment (SETDMAB)*
|
||||
;* READ reads the selected sector to the DMA*
|
||||
;* address, and WRITE writes the data from *
|
||||
;* the DMA address to the selected sector *
|
||||
;* (return 00 if successful, 01 if perm err)*
|
||||
;* *
|
||||
;*********************************************
|
||||
|
||||
READ:
|
||||
rs 50 ;fill-in
|
||||
ret
|
||||
|
||||
WRITE:
|
||||
rs 50 ;(fill-in)
|
||||
ret
|
||||
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* Data Areas *
|
||||
;* *
|
||||
;*********************************************
|
||||
data_offset equ offset $
|
||||
|
||||
dseg
|
||||
org data_offset ;contiguous with code segment
|
||||
IOBYTE db 0
|
||||
disk db 0 ;disk number
|
||||
trk dw 0 ;track number
|
||||
sect dw 0 ;sector number
|
||||
dma_adr dw 0 ;DMA offset from DS
|
||||
dma_seg dw 0 ;DMA Base Segment
|
||||
|
||||
IF loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
signon db cr,lf,cr,lf
|
||||
db 'CP/M-86 Version 1.0',cr,lf,0
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;loader_bios
|
||||
|
||||
IF not loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
signon db cr,lf,cr,lf
|
||||
db 'System Generated 00/00/00'
|
||||
db cr,lf,0
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;not loader_bios
|
||||
|
||||
int_trp db cr,lf
|
||||
db 'Interrupt Trap Halt'
|
||||
db cr,lf
|
||||
|
||||
; 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 2000h ;second is 20000 -
|
||||
dw 2000h ;3FFFF (128k)
|
||||
|
||||
include singles.lib ;read in disk definitions
|
||||
|
||||
loc_stk rw 32 ;local stack for initialization
|
||||
stkbase equ offset $
|
||||
|
||||
lastoff equ offset $
|
||||
tpa_seg equ (lastoff+0400h+15) / 16
|
||||
tpa_len equ 0800h - tpa_seg
|
||||
db 0 ;fill last address for GENCMD
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* Dummy Data Section *
|
||||
;* *
|
||||
;*********************************************
|
||||
dseg 0 ;absolute low memory
|
||||
org 0 ;(interrupt vectors)
|
||||
int0_offset rw 1
|
||||
int0_segment rw 1
|
||||
; pad to system call vector
|
||||
rw 2*(bdos_int-1)
|
||||
|
||||
bdos_offset rw 1
|
||||
bdos_segment rw 1
|
||||
END
|
||||
|
619
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/COPYDISK.A86
Normal file
619
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/COPYDISK.A86
Normal file
@@ -0,0 +1,619 @@
|
||||
title 'COPYDISK 1 Feb 82'
|
||||
|
||||
ver equ 20 ; Version 2.0 -jrp
|
||||
|
||||
; COPYDISK duplicates entire diskettes using all of the
|
||||
; available storage as a multiple track buffer.
|
||||
|
||||
; This program must be built with a large extra segment
|
||||
; as follows:
|
||||
|
||||
; ASM86 COPYDISK
|
||||
; GENCMD COPYDISK EXTRA[M0200,XFF00]
|
||||
|
||||
; This allows COPYDISK to utilize all the left-over memory in your
|
||||
; system as its buffer.
|
||||
|
||||
|
||||
|
||||
cseg ; code segment
|
||||
start:
|
||||
mov si,offset signon_message
|
||||
call pmsg ; print signon message
|
||||
next_copy:
|
||||
; reload local stack for retries.
|
||||
pushf ; save interrupt flag in stack
|
||||
pop bx ; put it in bx
|
||||
cli ; disable interrupts
|
||||
mov ax,ds ; get our data segment
|
||||
mov ss,ax ; and use as stack segment
|
||||
mov sp,offset stack_end ; set stack pointer
|
||||
push bx ; flags back into stack
|
||||
popf ; restore interrupt status
|
||||
|
||||
mov si,offset source_message ; prompt for source drive
|
||||
call get_drive ; request drive code
|
||||
cmp al, cr - 'A' ; see if it was a <cr>
|
||||
jne next_1 ; no, continue
|
||||
jmp exit ; yes, we should exit
|
||||
next_1:
|
||||
cmp al,drive_cnt ; see if valid drive code
|
||||
jb save_source ; yes, go save it
|
||||
drive_err:
|
||||
mov si,offset bad_drive ; else, print
|
||||
call pmsg ; a bad drive message
|
||||
jmp another ; and try to get another
|
||||
|
||||
save_source:
|
||||
mov source,al ; save it as the source drive
|
||||
add al,'A' ; make ascii drive code
|
||||
mov source_ascii,al ; save for messages
|
||||
|
||||
mov cl,source ; get source drive
|
||||
mov dl,0 ; force first time selection
|
||||
call seldsk ; select it
|
||||
test bx,bx ; insure the drive exists
|
||||
jz drive_err ; no, fatal
|
||||
mov si,ES:word ptr 10[bx] ; get pointer to DPB
|
||||
; create local copy of disk definition
|
||||
push ds ! push es ; save segments
|
||||
pop ds ! pop es ; and exchange them
|
||||
mov di,offset disk_def ; point to local disk def table
|
||||
mov cx,15 ; diskdef is 15 bytes long
|
||||
cld ! rep movsb ; copy it
|
||||
push ds ! push es ; swap back
|
||||
pop ds ! pop es ; segment registers
|
||||
|
||||
mov dx,es:word ptr 00[bx] ; get secttran table address
|
||||
mov cx,0 ; logical sector zero
|
||||
call sectran ; find out first sector number
|
||||
mov base_sector,bx ; save this for track reads
|
||||
|
||||
|
||||
mov si,offset dest_message ; prompt for destination
|
||||
call get_drive ; get the drive code
|
||||
cmp al,source ; see if same as source
|
||||
jne not_same ; no, go see if > max
|
||||
mov si,offset same_message ; can't have same drive
|
||||
call pmsg ; so we print message
|
||||
jmp another ; and go try again
|
||||
|
||||
not_same:
|
||||
cmp al,drive_cnt ; is dest > max?
|
||||
jnb drive_err ; go print invalid drive error
|
||||
|
||||
mov dest,al ; save destination drive
|
||||
add al,'A' ; make ascii drive code
|
||||
mov dest_ascii,al ; save for messages
|
||||
|
||||
mov cl,dest ; get destination drive
|
||||
mov dl,0 ; force first time selection
|
||||
call seldsk ; select destination drive
|
||||
test bx,bx ; insure drive exists
|
||||
jz drive_err ; no, go error out
|
||||
mov di,ES:word ptr 10[bx] ; point to destination DPB
|
||||
mov si,offset disk_def ; point to source drives def
|
||||
mov cx,15 ; length of a definition
|
||||
cld ! rep cmpsb ; compare the definitions
|
||||
je next_2 ; must be equal.
|
||||
jmp different_type ; else go print error
|
||||
next_2:
|
||||
mov dx,es:word ptr 00[bx] ; get secttran table address
|
||||
mov cx,0 ; logical sector zero
|
||||
call sectran ; find out first sector number
|
||||
cmp bx,base_sector ; make sure its the same
|
||||
je next_3 ; the same is OK,
|
||||
jmp different_type ; no, fatal error
|
||||
|
||||
next_3: ; determine track capacity
|
||||
mov ax,spt ; get the sectors per track
|
||||
mov dl,128 ; length of a sector
|
||||
mul dl ; get track capacity
|
||||
mov track_size,ax ; save it
|
||||
|
||||
; determine number of tracks on diskette
|
||||
mov al,blm ; get block mask
|
||||
inc al ; plus 1 gives sectors/block
|
||||
mov ah,0 ; make 16 bits
|
||||
mov dx,0 ; make 32 bits
|
||||
mul dsm ; total sectors/data area
|
||||
add ax,spt ; force round up
|
||||
dec ax ; by adding SPT-1
|
||||
div spt ; compute number of tracks
|
||||
add ax,off ; add in operating sys tracks
|
||||
dec ax ; number of last track
|
||||
mov max_track,ax ; save value
|
||||
|
||||
; compute number of tracks that will
|
||||
; fit in our data segment
|
||||
mov ax,extra_length ; get low 16 bits of DS length
|
||||
mov dl,extra_length_H ; get other 8 bits
|
||||
mov dh,0 ; zero rest of 32 bit divisor
|
||||
div track_size ; divide buff_len / track_size
|
||||
mov NTS,ax ; save this value.
|
||||
cmp ax,2 ; must be at least 2 tracks
|
||||
jae adequite_memory ; ok, continue
|
||||
mov si,offset memory_message ; else print
|
||||
call pmsg ; error message
|
||||
|
||||
aborting: ; here if exiting because of error
|
||||
mov si,offset abort_message
|
||||
call pmsg
|
||||
jmp another
|
||||
|
||||
|
||||
adequite_memory:
|
||||
|
||||
mov si,offset ready_message ; insure this is correct
|
||||
call get_yn ; print request
|
||||
jc aborting ; if NO, then get new input
|
||||
mov si,offset copy_message ; else tell user OK.
|
||||
call pmsg
|
||||
|
||||
mov ax,max_track ; get maximum track number
|
||||
mov base_track,ax ; save as outer loop index
|
||||
next_block:
|
||||
mov ax,base_track ; get loop index
|
||||
cmp ax,0 ; see if we are outside limits
|
||||
jl next_block_x ; yes, terminate loop
|
||||
sub ax,nts ; lower by number of tracks per buffer
|
||||
inc ax ; and adjust by 1.
|
||||
jns not_neg ; check to make sure its positive
|
||||
mov ax,0 ; no, zero is floor
|
||||
not_neg:
|
||||
mov btr,ax ; save as last track for this copy pass
|
||||
|
||||
mov si,offset reading_message ; point to read message
|
||||
mov ax,offset read ; and proper subroutine
|
||||
mov cl,source ; select source diskette
|
||||
call track_block
|
||||
|
||||
mov si,offset writing_message ; point to write message
|
||||
mov ax,offset write ; and proper subroutine
|
||||
mov cl,dest ; select destination
|
||||
call track_block
|
||||
|
||||
mov si,offset verify_message ; point to verify message
|
||||
mov ax,offset verify
|
||||
mov cl,dest ; reselect destination
|
||||
call track_block
|
||||
|
||||
mov ax,base_track
|
||||
sub ax,nts ; adjust base track by number we copied
|
||||
mov base_track,ax
|
||||
jmps next_block
|
||||
|
||||
next_block_x: ; here, we are done with a sucessful copy
|
||||
mov si,offset done_message ; print message
|
||||
call pmsg ; announcing success
|
||||
|
||||
another:
|
||||
mov si,offset another_message
|
||||
call getyn ; see if we want another copy
|
||||
jc exit ; no, go exit
|
||||
next_copy_v: ; convienient for short jumps
|
||||
jmp next_copy ; back for another disk copy
|
||||
|
||||
|
||||
exit: ; here, we are exiting
|
||||
mov si,offset exit_message
|
||||
call pmsg
|
||||
|
||||
mov cl,13
|
||||
int BDOS
|
||||
|
||||
mov cl,0 ; reboot
|
||||
mov dl,0 ; CP/M-86
|
||||
int BDOS
|
||||
|
||||
different_type:
|
||||
mov si,offset type_error_message
|
||||
call pmsg
|
||||
jmp aborting
|
||||
|
||||
track_block:
|
||||
mov message_pointer,si ; save pointer to message
|
||||
mov disk_function,ax ; save pointer to read/write
|
||||
mov selected_disk,cl ; save drive select code
|
||||
mov dl,1 ; tell bios have selected before
|
||||
call seldsk ; select diskette drive
|
||||
mov ax,base_track ; get base track number for this pass
|
||||
mov trk,ax ; save as loop index
|
||||
next_track: ; first inner loop...
|
||||
mov ax,trk ; get the index
|
||||
cmp ax,btr ; see if less than last
|
||||
jnl next_4 ; no, continue
|
||||
jmp next_track_x ; yeah, exit loop
|
||||
next_4:
|
||||
mov si,message_pointer
|
||||
call pmsg ; print "<xxxx> Track "
|
||||
mov ax,trk ; get the track number
|
||||
call pdec ; print as decimal
|
||||
mov si,offset space_message ; then, print some
|
||||
call pmsg ; spaces to blank any garbage
|
||||
mov cx,trk ; get desired track address
|
||||
call settrk ; give to bios
|
||||
mov cx,0 ; start with logical sector 0
|
||||
next_sector:
|
||||
push cx ; save current sector number
|
||||
mov sector,cx ; save sector number (0 org)
|
||||
add cx,base_sector ; correct for first sector number
|
||||
call setsec ; pass to cbios
|
||||
|
||||
; compute dma address and segment
|
||||
mov ax,base_track ; get starting track number
|
||||
sub ax,trk ; gives relative track of pass
|
||||
mov dx,0 ; make dword
|
||||
mul spt ; compute sector of track
|
||||
add ax,sector ; add in current logical sector
|
||||
adc dx,0 ; make double precision add
|
||||
mov cx,128 ; length of a sector
|
||||
mul cx ; gives base offset as 32 bits
|
||||
mov dma_offset,ax ; gives base dma offset
|
||||
mov cl,12 ! shl dx,cl ; move to high nibble
|
||||
add dx,extra_base ; offset extra segment
|
||||
mov dma_segment,dx ; save DMA segment
|
||||
mov cx,dx ; put in argument register
|
||||
call setdmab ; pass to CBIOS
|
||||
mov cx,dma_offset ; get the offset again
|
||||
call setdma ; and pass it to BIOS also
|
||||
|
||||
mov ax,sector ; fetch current sector number
|
||||
inc ax ; add one to it
|
||||
cmp ax,spt ; see if last sector on track
|
||||
mov cl,0 ; might be then normal write
|
||||
jb execute_function ; skip if not last
|
||||
mov cl,1 ; if last, then treating as
|
||||
; dir write forces flush
|
||||
execute_function:
|
||||
call disk_function ; read/write/verify a sector
|
||||
test al,al ; check error return code
|
||||
jz no_disk_error ; see if we got a bad sector
|
||||
|
||||
; got fatal disk error
|
||||
mov si,offset disk_error_message
|
||||
call pmsg ; print disk error
|
||||
mov si,message_pointer ; get pointer to read/write
|
||||
inc si ; skip leading <cr>
|
||||
call pmsg ; print that
|
||||
mov ax,trk ; get track number
|
||||
call pdec ; print it
|
||||
mov si,offset sector_message ; print ", Sector "
|
||||
call pmsg
|
||||
mov ax,sector ; get sector number (0 org)
|
||||
add ax,base_sector ; correct if 1 origin
|
||||
call pdec ; print the sector number
|
||||
mov si,offset continue_message ; see if user wants to ignore
|
||||
call get_yn ; ask for a Y/N response
|
||||
jnc next_5 ; yes, continue
|
||||
jmp aborting ; NO, go ask for new disks
|
||||
next_5:
|
||||
call crlf
|
||||
no_disk_error:
|
||||
pop cx ; recover sector number
|
||||
inc cx ; sector = sector + 1
|
||||
cmp cx,spt ; see if past last sector
|
||||
jae next_6 ; done, exit
|
||||
jmp next_sector ; else, continue
|
||||
next_6:
|
||||
dec trk ; track = track - 1
|
||||
jmp next_track ; continue loading buffer
|
||||
next_track_x:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
verify: ; verify a 128 byte sector
|
||||
mov cx,offset verify_buffer ; point at our 128 byte buffer
|
||||
call setdma ; make it the dma buffer
|
||||
mov cx,ds ; get our data segment
|
||||
call setdmab ; point dma base address
|
||||
call read ; read 128 byte record
|
||||
push ax ; save read error in stack
|
||||
mov si,offset verify_buffer ; point to sector we just read
|
||||
les di,dword ptr dma_offset ; get pointer to one we wrote
|
||||
mov cx,128 ; 128 byte record
|
||||
cld ! rep cmpsb ; compare them
|
||||
mov al,0 ; no error
|
||||
je verify_good ; so we are ok
|
||||
mov al,0FFh ; else, we got compare error
|
||||
verify_good:
|
||||
pop dx ; recover read error byte
|
||||
or al,dl ; merge into return code
|
||||
ret ; back to caller
|
||||
|
||||
|
||||
; ***********************************
|
||||
; *
|
||||
; * BIOS direct entry points
|
||||
; *
|
||||
; ***********************************
|
||||
|
||||
home:
|
||||
mov al,8
|
||||
jmps bios_call
|
||||
|
||||
seldsk:
|
||||
mov al,9
|
||||
jmps bios_call
|
||||
|
||||
settrk:
|
||||
mov al,10
|
||||
jmps bios_call
|
||||
|
||||
setsec:
|
||||
mov al,11
|
||||
jmps bios_call
|
||||
|
||||
setdma:
|
||||
mov al,12
|
||||
jmps bios_call
|
||||
|
||||
setdmab:
|
||||
mov al,17
|
||||
jmps bios_call
|
||||
|
||||
read:
|
||||
mov al,13
|
||||
jmps bios_call
|
||||
|
||||
write:
|
||||
mov al,14
|
||||
jmps bios_call
|
||||
|
||||
sectran:
|
||||
mov al,16
|
||||
jmps bios_call
|
||||
|
||||
bios_call:
|
||||
mov bios_function,al
|
||||
mov bios_CX,cx
|
||||
mov bios_DX,DX
|
||||
mov cl,50
|
||||
mov dx,offset bios_function
|
||||
int BDOS
|
||||
ret
|
||||
|
||||
|
||||
; ****************************************
|
||||
; *
|
||||
; * Operator interaction subroutines
|
||||
; *
|
||||
; ****************************************
|
||||
|
||||
get_drive: ; print message and read drive code
|
||||
call pmsg ; first, print the message
|
||||
call get_upper ; then get an upper case letter
|
||||
sub al,'A' ; and normalize to 0...
|
||||
ret
|
||||
|
||||
get_upper: ; get upper case console input w/ echo
|
||||
call get_char ; get console character
|
||||
cmp al,'a' ; see if lower case
|
||||
jb get_upper_x ; below, leave
|
||||
cmp al,'z' ; insure not > z
|
||||
ja get_upper_x ; not lower at all
|
||||
sub al,'a'-'A' ; make upper
|
||||
get_upper_x:
|
||||
ret
|
||||
|
||||
get_yn: ; print message and get Y or N
|
||||
push si ; save message pointer
|
||||
call pmsg ; print the message
|
||||
call get_upper ; get a upper case letter
|
||||
pop si ; recover message pointer
|
||||
cmp al,'Y' ; see if response was 'Y'
|
||||
je get_yn_x ; yes, return w/ no carry
|
||||
cmp al,'N' ; see if was 'N'
|
||||
jne get_yn ; no, invalid. reprompt
|
||||
stc ; set carry for a NO
|
||||
get_yn_x:
|
||||
ret
|
||||
|
||||
get_char: ; read a line from CONIN and return first char
|
||||
mov cl,10 ; function for line in
|
||||
mov dx,offset line_buff ; point at buffer
|
||||
int BDOS ; read the line
|
||||
mov al,line_buff+1 ; get input length
|
||||
cmp al,1 ; insure single char entered
|
||||
jb get_char_1 ; no, go
|
||||
mov al,line_buff+2 ; get the character
|
||||
ret
|
||||
get_char_1:
|
||||
mov al,cr ; null string, return a <CR>
|
||||
ret
|
||||
|
||||
|
||||
crlf: ; print a <CR><LF>
|
||||
mov si,offset crlf_message
|
||||
; fall into pmsg
|
||||
|
||||
pmsg: ; print message at [SI] to zero
|
||||
lods al ; get a character
|
||||
test al,al ; see if zero terminator
|
||||
jz pmsg_x ; yes, exit
|
||||
push si ; save pointer
|
||||
call conout ; not done, print character
|
||||
pop si ; recover pointer
|
||||
jmp pmsg ; and loop
|
||||
pmsg_x:
|
||||
ret
|
||||
|
||||
conin: ; get character from console into AL
|
||||
mov cl,6
|
||||
mov dl,0FFh
|
||||
int BDOS
|
||||
test al,al
|
||||
jz conin
|
||||
ret
|
||||
|
||||
conout: ; output character in AL to console
|
||||
mov dl,al
|
||||
mov cl,6
|
||||
int BDOS
|
||||
ret
|
||||
|
||||
pdec: ; print unsigned 16 bits in AX as decimal
|
||||
; with zero suppresion
|
||||
mov cx,0 ; cx is digit counter
|
||||
pdec_1: ; here to divide out next digit
|
||||
sub dx,dx ; Zero DX
|
||||
mov bx,10 ; constant 10
|
||||
div bx ; quotient to AX, remainder to DX
|
||||
add dl,'0' ; make remainder ascii digit
|
||||
push dx ; and stick onto stack
|
||||
inc cx ; bump digit counter
|
||||
test ax,ax ; see if any quotient left
|
||||
jnz pdec_1 ; yes, continue stacking digits
|
||||
pdec_2:
|
||||
pop ax ; get a digit from the stack
|
||||
push cx ; save count
|
||||
call conout ; print it
|
||||
pop cx ; restore count
|
||||
loop pdec_2 ; and continue if more in stack
|
||||
ret ; done. . .
|
||||
|
||||
|
||||
|
||||
; ** DATA SEGMENT **
|
||||
dseg
|
||||
|
||||
cr equ 0dh ; ascii carriage return
|
||||
lf equ 0ah ; ascii line feed
|
||||
|
||||
drive_cnt equ 16 ; CP/M currently supports up to 16 drives
|
||||
|
||||
BDOS equ 224 ; system call interrupt number
|
||||
|
||||
|
||||
; CP/M-86 Page Zero
|
||||
|
||||
code_length rw 1 ; low 16 bits code length
|
||||
code_length_H rb 1 ; high 8 bits '' ''
|
||||
code_base rw 1 ; base of the code segment
|
||||
model_8080 rb 1 ; 8080 memory model flag
|
||||
data_length rw 1 ; low 16 bits data length
|
||||
data_length_H rb 1 ; high 8 bits '' ''
|
||||
data_base rw 1 ; base of the data segment
|
||||
rs 1 ; not used
|
||||
extra_length rw 1 ; low 16 bits extra length
|
||||
extra_length_H rb 1 ; high 8 bits '' ''
|
||||
extra_base rw 1 ; base of the extra segment
|
||||
|
||||
|
||||
org 005Ch
|
||||
|
||||
default_FCB rs 35 ; default File Control Block
|
||||
|
||||
org 0080h
|
||||
|
||||
default_buffer rs 128 ; default record buffer
|
||||
|
||||
org 0100h ; start of user data segment
|
||||
|
||||
|
||||
; MESSAGES
|
||||
|
||||
signon_message db cr,lf,'CP/M-86 Full Disk COPY Utility'
|
||||
db cr,lf,' Version '
|
||||
db ver/10+'0', '.', (ver mod 10)+'0',cr,lf,0
|
||||
|
||||
source_message db cr,lf,cr,lf,'Enter Source Disk Drive (A-D) ? ',0
|
||||
|
||||
dest_message db cr,lf,cr,lf,' Destination Disk Drive (A-D) ? ',0
|
||||
|
||||
ready_message db cr,lf,cr,lf,'Copying Disk '
|
||||
source_ascii rb 1
|
||||
db ': to Disk '
|
||||
dest_ascii rb 1
|
||||
db ':',cr,lf
|
||||
db 'Is this what you want to do (Y/N) ? ',0
|
||||
|
||||
memory_message db cr,lf,'Insufficient memory available for copy',0
|
||||
|
||||
abort_message db cr,lf,cr,lf,'Copy aborted',cr,lf,0
|
||||
|
||||
done_message db cr,lf,'Copy completed.',0
|
||||
|
||||
another_message db cr,lf,cr,lf,'Copy another disk (Y/N) ? ',0
|
||||
|
||||
copy_message db cr,lf,'Copy started',cr,lf,0
|
||||
|
||||
reading_message db cr,' Reading Track ',0
|
||||
|
||||
writing_message db cr,' Writing Track ',0
|
||||
|
||||
verify_message db cr,'Verifying Track ',0
|
||||
|
||||
space_message db ' ',0
|
||||
|
||||
bad_drive db cr,lf,'Illegal Diskette Drive',cr,lf,0
|
||||
|
||||
same_message db cr,lf,'Source and Destination cannot be the same'
|
||||
db cr,lf,0
|
||||
|
||||
type_error_message db cr,lf,'Source and Destination disks must be'
|
||||
db cr,lf,'the same type',cr,lf,0
|
||||
|
||||
continue_message db cr,lf,'Ignore error (Y/N) ? ',0
|
||||
|
||||
sector_message db ', Sector ',0
|
||||
|
||||
disk_error_message db cr,lf,'Permanent Error ',0
|
||||
|
||||
crlf_message db cr,lf,0
|
||||
|
||||
exit_message db cr,lf,'COPY program exiting',cr,lf,0
|
||||
|
||||
|
||||
; VARIABLES
|
||||
|
||||
source rb 1 ; source drive select code
|
||||
dest rb 1 ; destination drive select code
|
||||
selected_disk rb 1 ; current drive select code
|
||||
trk rw 1 ; current track number
|
||||
sector rw 1 ; current sector number (0 origin)
|
||||
nts rw 1 ; number of tracks per buffer full
|
||||
base_track rw 1 ; starting track number for this pass
|
||||
track_size rw 1 ; size of each track in bytes
|
||||
btr rw 1 ; last track number of this pass
|
||||
dma_offset rw 1 ; current buffer offset
|
||||
dma_segment rw 1 ; current buffer segment base
|
||||
message_pointer rw 1 ; points to appropriate read/write message
|
||||
disk_function rw 1 ; points to '' '' '' subroutine
|
||||
base_sector rw 1 ; either 0 or 1 normally
|
||||
max_track rw 1 ; total number of tracks on disk
|
||||
|
||||
line_buff db 80
|
||||
db 0
|
||||
rb 80
|
||||
|
||||
bios_function rb 1 ; bios function number
|
||||
bios_cx rw 1 ; first argument for BIOS call
|
||||
bios_dx rw 1 ; second argument for BIOS call
|
||||
|
||||
|
||||
disk_def rs 0 ; disk definition table gets copied here
|
||||
spt rw 1 ; 128 byte sectors per track
|
||||
bsh rb 1 ; block shift factor
|
||||
blm rb 1 ; block mask
|
||||
exm rb 1 ; extent mask
|
||||
dsm rw 1 ; disk size in blocks
|
||||
drm rw 1 ; directory size
|
||||
al0 rb 1 ; alloc 0
|
||||
al1 rb 1 ; alloc 1
|
||||
cks rw 1 ; checksum size
|
||||
off rw 1 ; directory offset
|
||||
|
||||
rw 128
|
||||
stack_end rw 0
|
||||
|
||||
|
||||
verify_buffer rs 128 ; sector buffer for verify function
|
||||
|
||||
db 0 ; force out data segment
|
||||
|
||||
|
||||
end
|
||||
|
366
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/CPM.H86
Normal file
366
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/CPM.H86
Normal file
@@ -0,0 +1,366 @@
|
||||
:0400000300000000F9
|
||||
:1B000081E92A03E92103E902037F0020202020202020202020202020202020D4
|
||||
:1B001B81434F505952494748542028432920313938302C204449474954414CA0
|
||||
:0B003681205245534541524348202091
|
||||
:1B008B81CDE08CCD8EC5C3B10033D2EBF38AD0B102EBEDB02051E8F4FF59C32C
|
||||
:1B00A681B00DE8F5FFB00AEBF151E8F3FF5B8A070AC07501C34353E8D8FF5BC5
|
||||
:1B00C181EBF1BA2708B13BEBC1B93200BA3009EBB9B13AEBB5B10DEBB18AD085
|
||||
:1B00DC81B10EEBABE8A8FFA2CD08FEC0C3B10FEBF3C606470800BA2708EBF22D
|
||||
:1B00F781B110E8E4FF7401C3B99B09EB20B111EBD8B112EBD4BA2708EBF3B1C2
|
||||
:1B01128113EB1DE873FF0AC0C3B114EBF6BA2708EBF7E888FFE9B706B117EB16
|
||||
:1B012D8104B2FFB120E956FF3C6172063C7B7302245FC3F6060508FF7458F621
|
||||
:1B014881063909FF740533C0E887FFBA0608E890FF7444A01508FEC8A22608B0
|
||||
:1B016381BA0608E8B2FF7534BF0A00BE4B08B98000E8C502C606140800FE0E40
|
||||
:1B017E811508BA0608E871FF7417A03909E84CFFBB0B00E820FFE8320074119C
|
||||
:1B019981E85600E9BF01E85000B10ABA0900E8E1FEBB0B0033C92E8A0E0A00D4
|
||||
:1B01B481E30A8A07E87AFF880743E2F6882FC70635090B00C3B10BE8BDFE0A2D
|
||||
:1B01CF81C07501C3B101E8B3FE0AC0C3B119EB10B133EB0C8B160308E8F5FF9B
|
||||
:1B01EA81BA8000B11AE999FEF6060508FF7501C3B000A20508E8D8FEBA0608CE
|
||||
:1B020581E809FFA03909E9CCFEBFDC09BE000BB90600F3A6E302EB01C3F48A01
|
||||
:1B022081040AC07501C33C207303E9930157BF3B09B90900FCF2AE5FC38A0484
|
||||
:1B023B813C007501C33C207401C346EBF143C60720E2FAC351E8CCFF5974F26A
|
||||
:1B025681433C2A7504B03FEB01468807E2EBE8B8FF740346EBF8C3B80000BBF8
|
||||
:1B027181270803D853C6063A09008B363509E8B7FF8936370974081C40807C15
|
||||
:1B028C81013A7405A03909EB123C1077043C007705B4FF5BEB39A23A09464621
|
||||
:1B02A7818807B90800E8A0FFB903003C2E750146E895FF438BFB8BC1B90300B5
|
||||
:1B02C281FC33C0F3AA893635095BB90B0043803F3F7502FEC4E2F68A040AE42A
|
||||
:1B02DD81C3BF4409BB0600BE2808B90400F3A6740803F94B75F1B007C38A0480
|
||||
:1B02F8813C2075F78BC3C38CCAE8DBFEBA4B08E8E3FEC3C70635090B002E801D
|
||||
:1B0313813E0B000375062EC6060A0000BC3009E83E01EB2C2EC6060A0000BC90
|
||||
:1B032E813009518AC1B104D2D8240F8AD0A2CE08E8EFFDE892FDA20508E88890
|
||||
:1B034981FD58240FA23909E887FDE8A9FF2E803E0A0000751AFCBC3009E84111
|
||||
:1B036481FDE873FE0441E82BFDB03EE826FDE88AFFE8C8FDFCE85FFEA2390916
|
||||
:1B037F812E803E0B003B74D78B363509E8ABFE74CEE8DAFE752BF6063A09FFF5
|
||||
:1B039A817403E94503803E280820741AE835FF48BBE20903D803D88B17FFE240
|
||||
:1B03B581B99009EB03B95C09E9EFFCE8E3FC8B1E37098A073C20740C0AC0741F
|
||||
:1B03D0810853E8C3FC5B43EBEEB03FE8BAFCE8C5FC2EC6060A0000E974FFE89A
|
||||
:1B03EB8180FEF6063A09FF75CCBB2808B90B00803F207503B021C38A073C20F2
|
||||
:1B0406817427432C303C0A73B18AF0F6C5E075AA8AC5B103D2C002C572A00212
|
||||
:1B042181C5729C02C672988AE8FEC975D4C3803F20758C43FEC975F68AC5C3EE
|
||||
:1B043C81FCF3A4C3BB4B08B40002C103D88A07C3C606270800A03A090AC074FE
|
||||
:1B04578124FEC8BB39093A07741BEB1D8A16CE08E8C6FCEB11A03A090AC0740D
|
||||
:1B04728109FEC8BB39093A077501C3A03909E957FCC606F10901E82700803EF6
|
||||
:1B048D81F009007406B9AA09E817FCEB15C606F10900E81000803EF009007410
|
||||
:1B04A88106B9C509E800FCE92F032EC6060A0000C606F00900E8ADFD80FCFF56
|
||||
:1B04C3817503E9F8FEE881FFBB2808803F20750AB50BC6073F43FECD75F8B29C
|
||||
:1B04DE810052E829FC7503E8D2FE7503E99B00A0CD08B103D2C88AC8B00AE840
|
||||
:1B04F98145FFD0D0730EF606F109FF7515C606F00901EB70F606F109FF7407F2
|
||||
:1B051481C606F00901EB625A8AC2FEC2529090902403507514E87AFB51E8AB8F
|
||||
:1B052F81FC590441E86AFBB03AE865FBEB08E85EFBB03AE85BFBE856FBB501CC
|
||||
:1B054A818AC5E8F1FE247F3C20751358503C03750BB009E8E0FE247F3C20740F
|
||||
:1B05658116B020E835FBFEC580FD0C730A80FD0975D3E824FBEBCE58E849FC20
|
||||
:1B0580817506E883FBE960FF5AC32EC6060A0000E8DAFC80FC0B7521B9640994
|
||||
:1B059B81E811FBE89FFBBB0A00FE0F7403E9B3FD43803F597403E9AAFD43893E
|
||||
:1B05B6811E3509803E2808207467E889FEBA2708E848FBFEC07503E8EAFDEBF1
|
||||
:1B05D1814C2EC6060A0000E892FC754A803E2808207443E865FEE803FB74E1BE
|
||||
:1B05EC81E8B7FABBFF0081FB8000720A53E823FB5B751BBB000043BE4A080353
|
||||
:1B060781F38A043C1A741053E886FAE8B4FB5B7506EBD8FEC87503E9C001E841
|
||||
:1B06228191FDE845FEE996FD2EC6060A0000E83AFC75F2A03A0950E810FEE86D
|
||||
:1B063D81CDFA7402EB55BE2708BF3708B91000E8EDFD8B363509E8E3FB3C3DE0
|
||||
:1B06588174043C5F75354689363509E807FC752B588AE8BB3A098A070AC074E4
|
||||
:1B067381063AC5882F7519882FC606270800E888FA7408BA2708E89EFAEB9025
|
||||
:1B068E81E829FDEBF9E8D6FDEB38B96F09E811FAEBECE847FD3C21751AE8FC09
|
||||
:1B06A981F9E881FA0C303C39760950B031E8DFF9582C0AE8D9F9EB493C1072FE
|
||||
:1B06C48102EB098AD0803E2808207503E9EDFCA2CE08E857FAE90801B97B0912
|
||||
:1B06DF81E8CDF9EBA8E827FB803E280820751FA03A090AC07415FEC8A23909B2
|
||||
:1B06FA81A33109E8CAF90BDB74CCA03909E8D0F9E9D700803E3008207402EBEC
|
||||
:1B071581BAE833FDBF3008BE0008B90300F3A4BA2708E8C3F97506E83DFDE953
|
||||
:1B0730818EFCE88EF94074A4891E03088EC3E82BFD8CD88EC0E825FBBB3A0911
|
||||
:1B074B81538A07A22708B81000E819FB5B8A07A23708C606470800BF5C008E08
|
||||
:1B076681060308BE2708B92100E8CAFCBE0B00E8C1FA0AC0740EAC0AC07409C6
|
||||
:1B0781813C207402EBF5E8AFFAB500BF81004EACAA0AC07404FEC5EBF68AC5CB
|
||||
:1B079C81BF8000AABF0000268B45032EA3FB07268A45052EA2FA07E8F0F8E8CA
|
||||
:1B07B7812AFAC606CF08002EC6060A00008E0603088E1E0308BB0F00833F00F9
|
||||
:1B07D28174028E072EFF1EF907BC3009E9B1F8E888FCE886FAA028082C20BB03
|
||||
:1007ED813A090A077503E968FBE9C7FB00000000B8
|
||||
:15080082434D4400000000242424202020202053554200000097
|
||||
:0909308209000001000B00000027
|
||||
:1B093A8200203D5F2E3A3B3C3E2C444952535553455252454E2054595045451E
|
||||
:1B095582524120444952204E4F2046494C4500414C4C2028592F4E293F0046D1
|
||||
:1B097082494C4520455849535453004D454D4F5259204E4F5420415641494C99
|
||||
:1B098B8241424C450052454144204552524F52000D0A43414E4E4F5420434C6C
|
||||
:1B09A6824F5345000D0A4E4F4E2D53595354454D2046494C4528532920455818
|
||||
:1B09C182495354000D0A53595354454D2046494C45285329204558495354001C
|
||||
:1609DC82000A0000099A9A048A05D2052A06A0068304E40600008B
|
||||
:0409F682000000007B
|
||||
:0E0A5082446563656D626572203238203831EC
|
||||
:00000001FF
|
||||
:02000085000079
|
||||
:0D0A60823132206A616E7561727920383200
|
||||
:02000085000079
|
||||
:0400000300000A806F
|
||||
:1B0A8081260FAB156314B0151225FC15B515D315D815DE15EA15F115EC0A06CE
|
||||
:1B0A9B81209D1F2720A120A720D220EB20F420FD2003210C2115211B212121E1
|
||||
:1B0AB6812821BA172E2134213D2146215821612167216D217321F715F715C4A0
|
||||
:1B0AD18121D621F821F10A570F760F800FAC0FCE0FF40F06104410A4101D0EFF
|
||||
:0B0AEC81B022E9030BBBA024E94A16ED
|
||||
:1B0B0081000A0000099A1E8CC88ED88F069D2480F905740580F90D7205C606BE
|
||||
:1B0B1B81B124FF8C16942489269624803E98240174078CC88ED0BC8E248B1EE8
|
||||
:1B0B368196248E069424268B5F0481E300027401FB8CD85557560E078C062501
|
||||
:1B0B518123E81A005E5F5D8E062523FA8E1694248B269624C606B124008E1EDF
|
||||
:1B0B6C819D24CF891699248816102332C0A39B24A22723A21523A21323BB89FA
|
||||
:1B0B8781215380F929720980E90680F9367201C38AD9B7008ACA03DB2EFFA7CD
|
||||
:1B0BA281800ABBAB23E819003C037555EB10BBB623EB08BBC223EB03BBBD23EF
|
||||
:1B0BBD81E80300E96A0353E8D308A0A4240441A2A723B99B23E8CF0859E8CBEA
|
||||
:1B0BD88108E9AA071E5051C6062723FF880E282332ED8B3699248936A924BF42
|
||||
:1B0BF381C623893E99248E1E9D24FCF3A459581FC351B121EB0351B124E8CD7A
|
||||
:1B0C0E81FF59C30650518A0E282332ED8E069D24BEC6238B3EA924893E992470
|
||||
:1B0C2981FCF3A4595807C3B1148B16DC228E1E2323E805008CC88ED8C32EC66D
|
||||
:1B0C448106982401CDE0C353BAD722E8F0FF5BC350538B5C072B5C058B4507F2
|
||||
:1B0C5F812B45053BD8760287F75B58C32BDB2BD2C606E222FFB90800BE0C2286
|
||||
:1B0C7A81803C007466803C027505C606E22200837C0300743E8B4403A3D7221E
|
||||
:1B0C9581837C07008B440574038B4407A3D92251B13852E8A0FF5A59803E9BDF
|
||||
:1B0CB0812400743151B136E891FF59A1D922394405731D894407B138E880FF04
|
||||
:1B0CCB81EB18035C05837C0700740C035407730ABAF0FFEB05EB5B0354058307
|
||||
:1B0CE681C609E2900BD274298916D922B137E854FF803E9B24007419B135E822
|
||||
:1B0D018148FF3B1ED92277D7B137E83DFF8B16D9222BD3E82C008B3E9423A192
|
||||
:1B0D1C8123238CC93BC17508C6450401FE069323EB12BE0C22B9080038047403
|
||||
:1B0D37810883C609E2F7B0FFC3B000C3803EE222FF750B8B1E112203DA891E67
|
||||
:1B0D52811322C3B002E8D4FF837C0700742E8BFEB80300E8C6FF837C0700748D
|
||||
:1B0D6D8119E8E3FED1EA8BDA035C053B5C0776072B5C0703D3EB03895C070328
|
||||
:1B0D88815505895507C3B003E89BFF035405895407C3837C07007404034407C9
|
||||
:1B0DA381C3034405C3C606D62200A1D722803EE222FF750DC606D62201A30FCA
|
||||
:1B0DBE8122A3D422EB2CBE0C22B90800803C007419803C027503A3D422837C03
|
||||
:1B0DD9810300750E894403803C097503C60401E8AFFF83C609E2DAC383FD70C9
|
||||
:1B0DF481750E5306E835FE075BBD0000BE5422C383C510C38BD82500F0B1040E
|
||||
:1B0E0F81D2ECB104D3E383EB017302FECCC3A19D24A32323A19924A3DC22A1C2
|
||||
:1B0E2A819424A3E022A19624A3DE228CCAB133E806FEBA0C22B11AE8FEFDE82D
|
||||
:1B0E4581E9FD803E9B24007403E9CD00E817FE84C075F6E84DFFBA5422B11AA6
|
||||
:1B0E6081E8DFFDBD7000B90800BB0C2251803F0074248E4703BF00008B4F0141
|
||||
:1B0E7B81E31951E870FFB90800FCF3A583FF0075078CC280C6108EC259E2E7CE
|
||||
:1B0E96815983C309E2D08E06D4228C069B24BF0000B93000B000FCF3AABF00DB
|
||||
:1B0EB18100A0D62226884505B201BE0C22B908003814740783C609E2F7EB30A8
|
||||
:1B0ECC818B4403268945038B4405837C070074038B4407E826FF268865022652
|
||||
:1B0EE781891D803EE222FF750C83C7062688650226891DEB0AFEC283C70680D1
|
||||
:1B0F0281FA0876B5A1DC22A39924C606982400A1E022A39424A1DE22A39624A3
|
||||
:1B0F1D81C3C7069B24FFFFEBE0A010233C01741FC6060A0000803E93230177BB
|
||||
:1B0F388105E86801EB0EE8F2018B1E9423E8E900FE0E9323C606982400BB03BA
|
||||
:1B0F538125E9B7061E8E1E9D248BDA8A078B4F018B57031F5B33DB8AD802C04A
|
||||
:1B0F6E8102D881C30025FFE38916A2248BCAE8B415C38B1EA224891E25238BAB
|
||||
:1B0F89811EA024E9B211832E9423058B3E94238B0789058B4702894502C64582
|
||||
:1B0FA48104008006292301C3E89B01750A803E2A23007473E8ED01756E8B449A
|
||||
:1B0FBF810239470272038947028B048907EB53E87901755883C604FEC13A0EEB
|
||||
:1B0FDA812A23734DE8480275F08B440203042B073947027203894702EB2DE804
|
||||
:1B0FF58153017532E8DD01752DE86B01E88BFFEB1BE84101752083C604FEC166
|
||||
:1B1010813A0E2A237315E8100275F0E84302E86EFFA02A2388470432C0EB02A7
|
||||
:1B102B81B0FFA29B24C38B4702A3D9228B07A3D722BBD722E81101EB0EE80324
|
||||
:1B10468101807F04FF7505E8E300EBCF837F020074D3E86C0275CEE892027438
|
||||
:1B106181C9E863003C0075C2E8C40275168BFE8AE9E8E60274088B47020145D1
|
||||
:1B107C8102EBA2E83802EB9DE8D402750C8B0789048B4702014402EB8CE8B710
|
||||
:1B109781018B0789048B4702894402EBEF33C0A22923A29323B89323A394231F
|
||||
:1B10B281E881148BF38A0CD0E1D0E1FEC132EDBF2A23FCF3A4C38A0E2923B5D6
|
||||
:1B10CD8100BF8E238B073905742173178B150355020347023BC2750B8B450293
|
||||
:1B10E8812B4702894502EB4083EF05E2DCB0FFC38B47023B4502741173F30312
|
||||
:1B1103810589058B45022B4702894502EB1F8B45FB89058B45FD8945028A45D8
|
||||
:1B111E81FF88450483EF05E2D1FE0E29238306942305B000C3803E29230074AD
|
||||
:1B1139810F8B1E9423807F04007505E8EAFEEBEAC3B105E88DFA8B1E9924B18A
|
||||
:1B115481FFBE2723B0FF803E2923087308837F02007402FEC00AC0C3518B44D7
|
||||
:1B116F81022B470275098B048907E80B00EB078944020304890759C35156576C
|
||||
:1B118A81A02A23FEC8A22A232AC1740E8AC832ED03C98BFE83C604FCF3A55FB4
|
||||
:1B11A5815E59C3525733D2B5FF83C604FEC13A0E2A23730F8B44023BC272EE81
|
||||
:1B11C0818BD08AE98BFEEBE6B0FF8BF78ACDFEC57402FEC00AC05F5AC35257FD
|
||||
:1B11DB81BAFFFFB5FF83C604FEC13A0E2A2373168B44022B4702741A72EB3B77
|
||||
:1B11F681C273E78BD08AE98BFEEBDFB0FF8BF78ACDFEC57402FEC00AC05F5A1E
|
||||
:1B121181C38B47020307C353E8F6FF8946028BDEE8EEFF8946005BC35583ECED
|
||||
:1B122C81048BEC51B5FFE8E3FF8B073B04720A8B46003B46027202B5008AC5C3
|
||||
:1B1247815983C4045D0AC0C3A02A23FE062A23B404F6E48BF08DB42B23C3558B
|
||||
:1B12628183EC048BEC5251E8ACFF8B073B0475198B46023B460075075951E80F
|
||||
:1B127D8108FFEB3289048B4702294402EB288B46002B460275098B072B0489C2
|
||||
:1B1298814402EB178B072B04894402E8A9FF8B460289042B4600F7D8894402E3
|
||||
:1B12B381595A83C4045DC38B4702034402014502E8C1FEC351525653E8681204
|
||||
:1B12CE818A2F8BF383EE035BB1FF83C604FEC13ACD7309E845FF75F2B000EB11
|
||||
:1B12E98102B0FF5E5A590AC0C35583EC048BEC5651BE2723B1FF83C604FEC170
|
||||
:1B1304813A0E2A23731BE80BFF8B073B0473098B46023B047707EBE33B46000C
|
||||
:1B131F8173DEB000EB02B0FF595E83C4045D0AC0C35583EC048BECBE2723B1B1
|
||||
:1B133A81FF83C604FEC13A0E2A23730CE8CFFE8B072B460075EBEB02B0FF83C1
|
||||
:1B135581C4045D0AC0C35583EC048BECBE2723B1FF83C604FEC13A0E2A23733F
|
||||
:1B1370810CE8A4FE8B46022B0475EBEB02B0FF83C4045D0AC0C3BBE6228A07C4
|
||||
:1B138B81C607000AC07525E96C02E8EEFFE80A00721A508AC8E8C00058C33C4A
|
||||
:1B13A6810D740E3C0A740A3C0974063C0874023C20C3A0E6220AC0754BE84462
|
||||
:1B13C18102240174F1E838023C13753AE831023C03740332C0C3C606E522008B
|
||||
:1B13DC81803E932300750BE8200CA09B24A20508EB0EF606AF24FF740F803E57
|
||||
:1B13F7819323017508C6060A0000E948FBE926FBA2E622B001C3A0E3220AC08D
|
||||
:1B141281751651E8A0FF5951E8EE015951803EB624007403E8D301598AC1BB86
|
||||
:1B142D81E5223C7F7416FE073C207310FE0F8A070AC074088AC13C087503FE0A
|
||||
:1B1448810FC33C0A75FBC60700C38AC1E84EFF730A50B15EE8AEFF5980C9401D
|
||||
:1B14638180F90975A5B120E8A0FFA0E522240775F4C3E80500B120E88E01B115
|
||||
:1B147E8108E98901B123E886FFE81000A0E5223A06E42273E1B120E875FFEBC5
|
||||
:1B149981F0B10DE86EFFB10AE969FF8BF1AC3C2474C941518AC81E161FE8AE16
|
||||
:1B14B481FF1F59EBEBA0E522A2E4228B1E9924268A0F4353B5005153E8B7FE4F
|
||||
:1B14CF815B593C0D7503E9C6003C0A74F93C08750E0AED74E6FECDA0E522A27E
|
||||
:1B14EA81E322EB513C7F750C0AED74D4268A07FECD4BEB7C3C05750C5153E828
|
||||
:1B15058193FFC606E42200EBBE3C107506F616B624EBB23C1875145BA0E42215
|
||||
:1B152081BBE522903A07739190FE0FE847FFEBED3C157507E84BFF5BE97EFF35
|
||||
:1B153B813C12753551E83FFF595B53510AED740F43268A0FFECD5153E8FCFE80
|
||||
:1B1556815B59EBED53A0E3220AC074102A06E522A2E322E809FFFE0EE32275D3
|
||||
:1B157181F7EB9843268807FEC551538AC8E8D1FE5B59268A073C038AC5750B83
|
||||
:1B158C813C0175078CD88EC0E940FE3AC17303E92CFF5B26882FB10D8CD88EC4
|
||||
:1B15A781C0E962FEE8E7FDEB44E8620FEB3F8AC1FEC07409FEC0754CE84400F0
|
||||
:1B15C281EB30E83F000AC07503E9E60BE83000EB21E8630FEB1C8BCAE85F0FFF
|
||||
:1B15DD81C38BCA1E8E1E9D24E8BCFE1FC38E069D24E9C8FEE8C4FDA29B24C37A
|
||||
:1B15F881B001EBF8BB0F25EB0DBB0925EB08BB0625EB03BB0C25FF1E0022C33E
|
||||
:1B161381FFD3CBBB0622FF2751B5008BF28BFBFCF3A459C38A0EA424E8ED0E9A
|
||||
:1B162E8183FB0074508B1783C302891EEC2283C302891EEE2283C302891EF061
|
||||
:1B1649812283C30287DA891E09238B1EF222891EAD24BBF222B108E8B8FF8B80
|
||||
:1B16648116F422BBFA22B10FE8ACFFA00023BB1223C607FF0AC07403C6070007
|
||||
:1B167F81B0FF0AC0C3E8910E33C08B1EEE228907C38B161A23E8900EEB078A2D
|
||||
:1B169A810E0D23E88A0E0AC074DFBB0422E96FFF8B1EA624B102D3EB891E1AFC
|
||||
:1B16B58123891E1F23A11A23BA0000F736FA22528BC88B36EE22890C030E0789
|
||||
:1B16D08123E84A0E598B160923E8540E8BCBE9400EBBFC228A0FA01823D2E817
|
||||
:1B16EB818AE8B1072A0FA01723D2E002C5C38B1E992483C31003D9803E12235F
|
||||
:1B1706810074058A1FB700C303D98B1FC3E8CBFF8AC8B500E8DCFF891E1A2302
|
||||
:1B172181C38B1E1A230BDBC38A0EFC228B1E1A23D3E3891E1C23A0182322069F
|
||||
:1B173C81FD220AD8891E1A23C38B1E992483C30C8A07C3BA0F0003169924BB03
|
||||
:1B175781110003DAC3E8F0FF8A07A2182387DA8A07A21623E8D7FFA0FE222293
|
||||
:1B17728107A21723C3E8D5FFA00F233C02750232C002061823880787DAA01617
|
||||
:1B178D81238807C3B980008B1EF22232C0020743E2FBC3518A0EA424BB01000A
|
||||
:1B17A881D3E3590BD9C3A1E8228A0EA424D3E82401C38B0EE822E8DFFF891E31
|
||||
:1B17C381E8228B160123428B1EEC228917C3E81B00BA090003DA8A07D0D07318
|
||||
:1B17DE811BBB0A22EB08E8C7FF7411BB0822E92AFE8B1EF222A01E23B40003FC
|
||||
:1B17F981D8C38B1E992483C30E8A07C3E8F3FFC60700C3E8ECFF0C808807C390
|
||||
:1B1814818B16A6248B1EEC223B17C3E8F2FF72FA428917C3522BD38BDA5AC345
|
||||
:1B182F81B1FF8B161F238B1E0523E8ECFF73E051E84FFF8B1E1F23031EF622E8
|
||||
:1B184A8159FEC1740D3A07740BE8BEFF7306E85FFFC38807C3E8CDFFE819007B
|
||||
:1B186581B101E833FEEB06E80F00E81EFE8B0EA224E8BA0CBBA024EB088CD94C
|
||||
:1B188081E8B00CBBF2228B0FE9990C8B16F2228B1EA024B180068E069D24E89B
|
||||
:1B189B817EFD07C3BBA6248A07433A077502FEC0C3BBFFFF891EA624C38B164C
|
||||
:1B18B68101238B1EA62443891EA624E864FF7302EBE4A0A624240351B105D252
|
||||
:1B18D181E059A21E230AC0752651E8CCFDE88BFF59E94CFF8BD180E107FEC176
|
||||
:1B18EC818AE9B103D3EA8B1EF82203DA8A078ACDD2C08BD1C352E8E0FF24FE08
|
||||
:1B190781590AC1518ACED2C8880759C3E8D9FE83C31051B1115AFEC97501C3B0
|
||||
:1B19228152803E122300740851538A0FB500EB07FEC9518B0F43530BC9740BE9
|
||||
:1B193D818B1EFF223BD97203E8B9FF5B4359EBCF8B1EFF22B103D3EB438BCB95
|
||||
:1B1958818B1EF822C6070043E2FA8B1603238B1EF8228917E815FD8B1EEC2269
|
||||
:1B197381C7070300E832FFB1FFE835FFE81DFF743BE868FE803FE574EEA0A5D6
|
||||
:1B198E81243A07750C438A072C247505FEC8A29B24B101E86FFFE878FEEBD1F0
|
||||
:1B19A981A00E23E945FC518A2EFE22F6D522CD22C52AC1241F59C38B1E99242D
|
||||
:1B19C481891E2123C6060E23FF880EA824C3E8EBFFE8D4FEE8A9FCC6069A23D9
|
||||
:1B19DF8100B100E8CFFEE8B7FE7503E980008B1621238BF2AC3CE5740752E8A4
|
||||
:1B19FA8118FE5A73EBE8EDFD8A0EA824B5000AC974388BF2AC3C3F742980FD5B
|
||||
:1B1A15810D742480FD0C74082A07247F7533EB17518A0FE884FF599FF6069A2A
|
||||
:1B1A308123FF7545C6069723009E759F4243FEC5FEC9EBC4C6060E2300A0A605
|
||||
:1B1A4B81242403A29B248AE8FEC5C30AED7530F607FF752BF6069723FF7424D6
|
||||
:1B1A6681C6069A23FFEBCFE83CFEB0FF8AE8FEC5E97BFB9E750E43803F0075A5
|
||||
:1B1A8181088B36A62489369823E94EFFE854FDB10CE83DFFE807FE74BBE83434
|
||||
:1B1A9C81FDE84FFDC607E5B100E86BFEE8B4FDE82DFFEBE58BD10BC9740C4953
|
||||
:1B1AB7815251E829FED0D87318595A3B16FF22731A4251528BCAE815FED0D81F
|
||||
:1B1AD28173045A59EBDAD0D0FEC0E82BFE5B5AC30BC975CCBB0000C3B100B2AC
|
||||
:1B1AED812052B5008B16992403D1E8F5FC59E81DFBE8A9FBE95BFDE8DDFCB193
|
||||
:1B1B08810CE8C6FE8B1E99248A0783C3108807E885FD7501C3E8B1FCB110B202
|
||||
:1B1B23810CE8C7FFE8B1FEEBEBB10CE8A1FEE86BFD74E6B100B20CE8B1FFE822
|
||||
:1B1B3E819BFEEBEFB10FE88BFEE855FD74D0E8F6FB5053E89BFC87DA8B1E994B
|
||||
:1B1B598124B12052E8BBFAE8A9FC5ABB0C0003DA8A0FBB0F0003DA8A2F5B58D5
|
||||
:1B1B748188073A0F8AC57406B0007202B0808B1E9924BA0F0003DA8807C383FF
|
||||
:1B1B8F813F0075FA8BF2AD8907C333C0A29B24A3A624E80AFC75F2E852FC241F
|
||||
:1B1BAA818075EBB10FE820FEE8EAFC74E1B91000E832FC03D987DA8B1E992454
|
||||
:1B1BC58103D9B110803E122300741B8A070AC08BF2AC750288070AC075068A0C
|
||||
:1B1BE081078BFAFCAA3A077547EB16E8A0FF87DAE89BFF87DA8BF28B043B0720
|
||||
:1B1BFB8175334243FEC94243FEC975C2B9ECFF03D987DA03D98BF2AC3A07723E
|
||||
:1B1C1681118807B9030003D987DA03D98A078BFAFCAAC6060B23FFE9CEFEFE55
|
||||
:1B1C31810E9B24C3E8ACFBFF369924C7069924E722B101E88BFDE855FC8F0683
|
||||
:1B1C4C81992474E48B169924BB0F0003DAB11132C0880743FEC975F9BB0D005F
|
||||
:1B1C678103DA8807E8B1FBE879FEE998FB32C0A20B23E81DFFE820FC74B38B8A
|
||||
:1B1C82811E992483C30C8A07FEC0241F8807740F8AE8A0FE2222C522060B2386
|
||||
:1B1C9D81740DEB2683C302FE078A07240F7426B10FE821FDE8EBFB7511A00CA8
|
||||
:1B1CB88123FEC07415E875FFE8DCFB740DEB03E882FEE88FFA32C0E922F9E8E5
|
||||
:1B1CD38123F9E934FBC6060F2301C6060C23FFE877FAA018233A061623721811
|
||||
:1B1CEE813C807528E87FFFE857FA33C0A318238807803E9B24007514E80AFA10
|
||||
:1B1D0981E816FA740CE818FAE8A6F9E879F9E95DFAE9DBF8C6060F2301C60624
|
||||
:1B1D24810C2300E8BAFA8B1E9924E8A3FAE828FAA018233C807203E9BAF8E8D4
|
||||
:1B1D3F81D2F9E8DEF9B1007548E896F9A2112333C90AC074088AC849E89FF966
|
||||
:1B1D5A818BCBE851FD0BDB7505B002E98CF8891E1A2387DA8B1E992483C310E1
|
||||
:1B1D7581803E122300A01123B400740603D88817EB0703D803D8891743B10225
|
||||
:1B1D9081803E9B24007401C3880E0D23E88AF9803E0F23027545803E0D230235
|
||||
:1B1DAB81753EFF361A238B3EF22233C0B94000FCF3ABE8BEFA8B1E1C23891EE5
|
||||
:1B1DC6811A23E8EFF8E8CBF88B1E1A23C6060D23008AC38A36FD2222C6433A57
|
||||
:1B1DE181C675E08F061A23E887FAE8CCF8E8A8F8A01823BB16233A07720688CC
|
||||
:1B1DFC8107FE07B10250E8F6F9247F8807583C7F751E803E0F23017517E85FC9
|
||||
:1B1E1781F9E859FEBB9B248A070AC07505FEC8A21823C60700E948F9C6060F33
|
||||
:1B1E32812300518B169924BB210003DA8A07247F508A07D0D0438A07D0D0243C
|
||||
:1B1E4D811F8AC88A07D0D8D0D8D0D8D0D8240F8AE858438A1F0ADBB3067569F2
|
||||
:1B1E6881BB200003DA8807BB0C0003DA8AC12A07750DBB0E0003DA8AC52A07CF
|
||||
:1B1E8381247F743C5152E80DFD5A59B303A09B24FEC07432BB0C0003DA880F74
|
||||
:1B1E9E81BB0E0003DA882FE89AFCA09B24FEC075145951B304FEC17412E87B1E
|
||||
:1B1EB981FDB305A09B24FEC074065932C0E92BF753E82EF9C607C05B598AC3FB
|
||||
:1B1ED481A29B24E932F9B1FFE850FF7503E8F9FDC3B100E845FF7503E833FE8F
|
||||
:1B1EEF81C387DA03DA8A0FB500BB0C0003DA8A27B000D1E880E40F03C8BB0E43
|
||||
:1B1F0A810003DA8A07B410F6E45002E89C5B8AC35B0AC32401C3B10CE8ADFA55
|
||||
:1B1F25818B1E9924BA210003DA538837438837438837E865F97422E8B0F8BAC6
|
||||
:1B1F40810F00E8ABFF5B538AD08BC12B078AC21A47027205885702890FE87FD8
|
||||
:1B1F5B81FAEBD95BC38B1E9924BA2000E886FFBB210003DA890F884702C38BF1
|
||||
:1B1F76811EEA228A0EA424D3CB5387DAE8A2F65B7503E88BF6D0DB72678B0E1A
|
||||
:1B1F9181EA22E80AF8891EEA22E9B0F9A01023A2A424EBD0E85CECEB03E85C1F
|
||||
:1B1FAC81EC8B1E9924C606962300F647088074098067087FC606962360C60661
|
||||
:1B1FC7811323FF8B1E99248A07241FFEC8A210233C1E7312A0A424A214238ACA
|
||||
:1B1FE28107A2152324E08807E8B0FFA0A5248B1E99240807C3803E962360756B
|
||||
:1B1FFD81078B1E9924C60700C3F7060222FFFF75048C0E022233DB891EE82236
|
||||
:1B201881891EEA228A1EB724881EA424E94EFFE87BFFE8D8F7803EA52400743E
|
||||
:1B2033810BC7069923FE00C6069723FFE800FBE83C00F6069723FF7501C3C63F
|
||||
:1B204E8106972300813E9923FE0074F28B1E982380E3FC4B891EA624C6069676
|
||||
:1B20698123608B1E9924C60700B10FE849F9E861F9E8CDFAE80100C3E81BF8A3
|
||||
:1B20848174C65B803E96236075128B1E99248A470A24807507A29623B0FFEB77
|
||||
:1B209F817EC3E801FFE9F2FAE85AEB8B1E9D24891EAB24B1008B1E9924803FC4
|
||||
:1B20BA813F7410E885F6803F3F7403E83DF7E8E2FEB10FE802F9EB168B1EAB13
|
||||
:1B20D58124891E9D248B1EA924891E9924E8C0FEE8F3F8E9A0F7E8B7FEE89CEF
|
||||
:1B20F081F9E9B5F8E8AEFEE8FDFEE9DBFBE8A5FEE91AFCE89FFEE8FCF6E92994
|
||||
:1B210B81FBE896FEE8F2F9E994F88B1EEA22EB26A0A424E9D3F48916A024E94F
|
||||
:1B2126814AF78B1EF822EB138B1EE822EB0DE86EFEE8F2F9E96CF88B1EF4223D
|
||||
:1B214181891E9B24C3A010233CFF7505A0A524EBCC241FA2A524C3E84FFEE8A3
|
||||
:1B215C8199FEE979FDE846FEE97EFDE840FEE9B3FDE899EAE9EDFDA19924F70F
|
||||
:1B217781D050BBEA222307890758BBE82223078907C3803E13230074248B1E5C
|
||||
:1B2192819924803E9623607504804F0880C60700A015230AC0740B8807A0141C
|
||||
:1B21AD8123A21023E8E9FD803E2723FF7503E853EAA19B248BD8C3E8E3FDC618
|
||||
:1B21C881060F2302B100E863FC75F0E94CFB1EB98000BF0B008B36A0248E1E62
|
||||
:1621E381A224AC0AC07403AAE2F8B0802AC1A20A001FE93AEDC375
|
||||
:02000086000078
|
||||
:0C22008213160000A40BB00BB50BBA0B38
|
||||
:1B22D48200000000000000000000000000000000000000E50000000000000088
|
||||
:1B22EF8200000000000000000000000000000000000000000000000000000052
|
||||
:1B230A8200000000000000000000000000000000000000000000000000000036
|
||||
:1B2325820000000000000000000000000000000000000000000000000000001B
|
||||
:1B23408200000000000000000000000000000000000000000000000000000000
|
||||
:10235B8200000000000000000000000000000000F0
|
||||
:1B239382000000000000000042646F7320457272204F6E20203A20244261643A
|
||||
:1823AE8220536563746F722453656C6563742446696C6520522F4F24C9
|
||||
:0B2494820000000000000000000000BB
|
||||
:1B24A0820000000000000000000000000000000000000000000000000000009F
|
||||
:0224BB8200009D
|
||||
:0124C8820091
|
||||
:0224E082500028
|
||||
:0124FA82005F
|
||||
:00000001FF
|
||||
:0400000300000521D3
|
||||
:03052181E91C054C
|
||||
:0F0A4081803EE0243C7203E9DAFA2401E9D5FA19
|
||||
:00000001FF
|
||||
:180A00823132204A616E75617279203139383200000000000012018276
|
||||
:00000001FF
|
||||
:04000003000021E6F2
|
||||
:0521E681AA0AC0740289
|
||||
:0421F1811FA20A009E
|
||||
:00000001FF
|
||||
:0400000300000A30BF
|
||||
:0F0A3081A12323A39D24C7069B24FFFFE9C704AD
|
||||
:030F1E81E90FFB5C
|
||||
:00000001FF
|
||||
:0400000300000B7777
|
||||
:020B778133C008
|
||||
:00000001FF
|
||||
:04000003000018964B
|
||||
:041896818E06A22473
|
||||
:00000001FF
|
||||
:0400000300000E23C8
|
||||
:060E238106908916DC2215
|
||||
:040F1A81E903FB90DB
|
||||
:050A2081A3962407C329
|
||||
:00000001FF
|
||||
:0400000300000A509F
|
||||
:0C0A50817207C7069B24FFFFC3E93B012E
|
||||
:030B9481E9B9FE3D
|
||||
:00000001FF
|
||||
:0400000300000A00EF
|
||||
:1B0A00812EC606982401502E8A2627232EA0132350CDE0582EA213232E8826F0
|
||||
:050A1B81272358C39060
|
||||
:090C4281E9BBFD90909090909027
|
||||
:00000001FF
|
||||
|
349
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/DEBLOCK.LIB
Normal file
349
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/DEBLOCK.LIB
Normal file
@@ -0,0 +1,349 @@
|
||||
;*****************************************************
|
||||
;* *
|
||||
;* Sector Blocking / Deblocking *
|
||||
;* *
|
||||
;* This algorithm is a direct translation of the *
|
||||
;* CP/M-80 Version, and is included here for refer- *
|
||||
;* ence purposes only. The file DEBLOCK.LIB is in- *
|
||||
;* cluded on your CP/M-86 disk, and should be used *
|
||||
;* for actual applications. You may wish to contact *
|
||||
;* Digital Research for notices of updates. *
|
||||
;* *
|
||||
;*****************************************************
|
||||
;
|
||||
;*****************************************************
|
||||
;* *
|
||||
;* CP/M to host disk constants *
|
||||
;* *
|
||||
;* (This example is setup for CP/M block size of 16K *
|
||||
;* with a host sector size of 512 bytes, and 12 sec- *
|
||||
;* tors per track. Blksiz, hstsiz, hstspt, hstblk *
|
||||
;* and secshf may change for different hardware.) *
|
||||
;*****************************************************
|
||||
una equ byte ptr [BX] ;name for byte at BX
|
||||
;
|
||||
blksiz equ 16384 ;CP/M allocation size
|
||||
hstsiz equ 512 ;host disk sector size
|
||||
hstspt equ 12 ;host disk sectors/trk
|
||||
hstblk equ hstsiz/128 ;CP/M sects/host buff
|
||||
;
|
||||
;*****************************************************
|
||||
;* *
|
||||
;* secshf is log2(hstblk), and is listed below for *
|
||||
;* values of hstsiz up to 2048. *
|
||||
;* *
|
||||
;* hstsiz hstblk secshf *
|
||||
;* 256 2 1 *
|
||||
;* 512 4 2 *
|
||||
;* 1024 8 3 *
|
||||
;* 2048 16 4 *
|
||||
;* *
|
||||
;*****************************************************
|
||||
secshf equ 2 ;log2(hstblk)
|
||||
cpmspt equ hstblk * hstspt ;CP/M sectors/track
|
||||
secmsk equ hstblk-1 ;sector mask
|
||||
;
|
||||
;*****************************************************
|
||||
;* *
|
||||
;* BDOS constants on entry to write *
|
||||
;* *
|
||||
;*****************************************************
|
||||
wrall equ 0 ;write to allocated
|
||||
wrdir equ 1 ;write to directory
|
||||
wrual equ 2 ;write to unallocated
|
||||
;
|
||||
;*****************************************************
|
||||
;* *
|
||||
;* The BIOS entry points given below show the *
|
||||
;* code which is relevant to deblocking only. *
|
||||
;* *
|
||||
;*****************************************************
|
||||
seldsk:
|
||||
;select disk
|
||||
;is this the first activation of the drive?
|
||||
test DL,1 ;lsb = 0?
|
||||
jnz selset
|
||||
;this is the first activation, clear host buff
|
||||
mov hstact,0
|
||||
mov unacnt,0
|
||||
selset:
|
||||
mov al,cl ! cbw ;put in AX
|
||||
mov sekdsk,al ;seek disk number
|
||||
mov cl,4 ! shl al,cl ;times 16
|
||||
add ax,offset dpbase
|
||||
mov bx,ax
|
||||
ret
|
||||
;
|
||||
home:
|
||||
;home the selected disk
|
||||
mov al,hstwrt ;check for pending write
|
||||
test al,al
|
||||
jnz homed
|
||||
mov hstact,0 ;clear host active flag
|
||||
homed:
|
||||
mov cx,0 ;now, set track zero
|
||||
; (continue HOME routine)
|
||||
ret
|
||||
;
|
||||
settrk:
|
||||
;set track given by registers CX
|
||||
mov sektrk,CX ;track to seek
|
||||
ret
|
||||
;
|
||||
setsec:
|
||||
;set sector given by register cl
|
||||
mov seksec,cl ;sector to seek
|
||||
ret
|
||||
;
|
||||
setdma:
|
||||
;set dma address given by CX
|
||||
mov dma_off,CX
|
||||
ret
|
||||
;
|
||||
setdmab:
|
||||
;set segment address given by CX
|
||||
mov dma_seg,CX
|
||||
ret
|
||||
;
|
||||
sectran:
|
||||
;translate sector number CX with table at [DX]
|
||||
test DX,DX ;test for hard skewed
|
||||
jz notran ;(blocked must be hard skewed)
|
||||
mov BX,CX
|
||||
add BX,DX
|
||||
mov BL,[BX]
|
||||
ret
|
||||
no_tran:
|
||||
;hard skewed disk, physical = logical sector
|
||||
mov BX,CX
|
||||
ret
|
||||
;
|
||||
read:
|
||||
;read the selected CP/M sector
|
||||
mov unacnt,0 ;clear unallocated counter
|
||||
mov readop,1 ;read operation
|
||||
mov rsflag,1 ;must read data
|
||||
mov wrtype,wrual ;treat as unalloc
|
||||
jmp rwoper ;to perform the read
|
||||
;
|
||||
write:
|
||||
;write the selected CP/M sector
|
||||
mov readop,0 ;write operation
|
||||
mov wrtype,cl
|
||||
cmp cl,wrual ;write unallocated?
|
||||
jnz chkuna ;check for unalloc
|
||||
;
|
||||
; write to unallocated, set parameters
|
||||
;
|
||||
mov unacnt,(blksiz/128) ;next unalloc recs
|
||||
mov al,sekdsk ;disk to seek
|
||||
mov unadsk,al ;unadsk = sekdsk
|
||||
mov ax,sektrk
|
||||
mov unatrk,ax ;unatrk = sektrk
|
||||
mov al,seksec
|
||||
mov unasec,al ;unasec = seksec
|
||||
;
|
||||
chkuna:
|
||||
;check for write to unallocated sector
|
||||
;
|
||||
mov bx,offset unacnt ;point "UNA" at UNACNT
|
||||
mov al,una ! test al,al ;any unalloc remain?
|
||||
jz alloc ;skip if not
|
||||
;
|
||||
; more unallocated records remain
|
||||
dec al ;unacnt = unacnt-1
|
||||
mov una,al
|
||||
mov al,sekdsk ;same disk?
|
||||
mov BX,offset unadsk
|
||||
cmp al,una ;sekdsk = unadsk?
|
||||
jnz alloc ;skip if not
|
||||
;
|
||||
; disks are the same
|
||||
mov AX, unatrk
|
||||
cmp AX, sektrk
|
||||
jnz alloc ;skip if not
|
||||
;
|
||||
; tracks are the same
|
||||
mov al,seksec ;same sector?
|
||||
;
|
||||
mov BX,offset unasec ;point una at unasec
|
||||
;
|
||||
cmp al,una ;seksec = unasec?
|
||||
jnz alloc ;skip if not
|
||||
;
|
||||
; match, move to next sector for future ref
|
||||
inc una ;unasec = unasec+1
|
||||
mov al,una ;end of track?
|
||||
cmp al,cpmspt ;count CP/M sectors
|
||||
jb noovf ;skip if below
|
||||
;
|
||||
; overflow to next track
|
||||
mov una,0 ;unasec = 0
|
||||
inc unatrk ;unatrk=unatrk+1
|
||||
;
|
||||
noovf:
|
||||
;match found, mark as unnecessary read
|
||||
mov rsflag,0 ;rsflag = 0
|
||||
jmps rwoper ;to perform the write
|
||||
;
|
||||
alloc:
|
||||
;not an unallocated record, requires pre-read
|
||||
mov unacnt,0 ;unacnt = 0
|
||||
mov rsflag,1 ;rsflag = 1
|
||||
;drop through to rwoper
|
||||
;
|
||||
;*****************************************************
|
||||
;* *
|
||||
;* Common code for READ and WRITE follows *
|
||||
;* *
|
||||
;*****************************************************
|
||||
rwoper:
|
||||
;enter here to perform the read/write
|
||||
mov erflag,0 ;no errors (yet)
|
||||
mov al, seksec ;compute host sector
|
||||
mov cl, secshf
|
||||
shr al,cl
|
||||
mov sekhst,al ;host sector to seek
|
||||
;
|
||||
; active host sector?
|
||||
mov al,1
|
||||
xchg al,hstact ;always becomes 1
|
||||
test al,al ;was it already?
|
||||
jz filhst ;fill host if not
|
||||
;
|
||||
; host buffer active, same as seek buffer?
|
||||
mov al,sekdsk
|
||||
cmp al,hstdsk ;sekdsk = hstdsk?
|
||||
jnz nomatch
|
||||
;
|
||||
; same disk, same track?
|
||||
mov ax,hsttrk
|
||||
cmp ax,sektrk ;host track same as seek track
|
||||
jnz nomatch
|
||||
;
|
||||
; same disk, same track, same buffer?
|
||||
mov al,sekhst
|
||||
cmp al,hstsec ;sekhst = hstsec?
|
||||
jz match ;skip if match
|
||||
nomatch:
|
||||
;proper disk, but not correct sector
|
||||
mov al, hstwrt
|
||||
test al,al ;"dirty" buffer ?
|
||||
jz filhst ;no, don't need to write
|
||||
call writehst ;yes, clear host buff
|
||||
; (check errors here)
|
||||
;
|
||||
filhst:
|
||||
;may have to fill the host buffer
|
||||
mov al,sekdsk ! mov hstdsk,al
|
||||
mov ax,sektrk ! mov hsttrk,ax
|
||||
mov al,sekhst ! mov hstsec,al
|
||||
mov al,rsflag
|
||||
test al,al ;need to read?
|
||||
jz filhst1
|
||||
;
|
||||
call readhst ;yes, if 1
|
||||
; (check errors here)
|
||||
;
|
||||
filhst1:
|
||||
mov hstwrt,0 ;no pending write
|
||||
;
|
||||
match:
|
||||
;copy data to or from buffer depending on "readop"
|
||||
mov al,seksec ;mask buffer number
|
||||
and ax,secmsk ;least signif bits are masked
|
||||
mov cl, 7 ! shl ax,cl ;shift left 7 (* 128 = 2**7)
|
||||
;
|
||||
; ax has relative host buffer offset
|
||||
;
|
||||
add ax,offset hstbuf ;ax has buffer address
|
||||
mov si,ax ;put in source index register
|
||||
mov di,dma_off ;user buffer is dest if readop
|
||||
;
|
||||
push DS ! push ES ;save segment registers
|
||||
;
|
||||
mov ES,dma_seg ;set destseg to the users seg
|
||||
;SI/DI and DS/ES is swapped
|
||||
;if write op
|
||||
mov cx,128/2 ;length of move in words
|
||||
mov al,readop
|
||||
test al,al ;which way?
|
||||
jnz rwmove ;skip if read
|
||||
;
|
||||
; write operation, mark and switch direction
|
||||
mov hstwrt,1 ;hstwrt = 1 (dirty buffer now)
|
||||
xchg si,di ;source/dest index swap
|
||||
mov ax,DS
|
||||
mov ES,ax
|
||||
mov DS,dma_seg ;setup DS,ES for write
|
||||
;
|
||||
rwmove:
|
||||
cld ! rep movs AX,AX ;move as 16 bit words
|
||||
pop ES ! pop DS ;restore segment registers
|
||||
;
|
||||
; data has been moved to/from host buffer
|
||||
cmp wrtype,wrdir ;write type to directory?
|
||||
mov al,erflag ;in case of errors
|
||||
jnz return_rw ;no further processing
|
||||
;
|
||||
; clear host buffer for directory write
|
||||
test al,al ;errors?
|
||||
jnz return_rw ;skip if so
|
||||
mov hstwrt,0 ;buffer written
|
||||
call writehst
|
||||
mov al,erflag
|
||||
return_rw:
|
||||
ret
|
||||
;
|
||||
;*****************************************************
|
||||
;* *
|
||||
;* WRITEHST performs the physical write to the host *
|
||||
;* disk, while READHST reads the physical disk. *
|
||||
;* *
|
||||
;*****************************************************
|
||||
writehst:
|
||||
ret
|
||||
;
|
||||
readhst:
|
||||
ret
|
||||
;
|
||||
;*****************************************************
|
||||
;* *
|
||||
;* Use the GENDEF utility to create disk def tables *
|
||||
;* *
|
||||
;*****************************************************
|
||||
dpbase equ offset $
|
||||
; disk parameter tables go here
|
||||
;
|
||||
;*****************************************************
|
||||
;* *
|
||||
;* Uninitialized RAM areas follow, including the *
|
||||
;* areas created by the GENDEF utility listed above. *
|
||||
;* *
|
||||
;*****************************************************
|
||||
sek_dsk rb 1 ;seek disk number
|
||||
sek_trk rw 1 ;seek track number
|
||||
sek_sec rb 1 ;seek sector number
|
||||
;
|
||||
hst_dsk rb 1 ;host disk number
|
||||
hst_trk rw 1 ;host track number
|
||||
hst_sec rb 1 ;host sector number
|
||||
;
|
||||
sek_hst rb 1 ;seek shr secshf
|
||||
hst_act rb 1 ;host active flag
|
||||
hst_wrt rb 1 ;host written flag
|
||||
;
|
||||
una_cnt rb 1 ;unalloc rec cnt
|
||||
una_dsk rb 1 ;last unalloc disk
|
||||
una_trk rw 1 ;last unalloc track
|
||||
una_sec rb 1 ;last unalloc sector
|
||||
;
|
||||
erflag rb 1 ;error reporting
|
||||
rsflag rb 1 ;read sector flag
|
||||
readop rb 1 ;1 if read operation
|
||||
wrtype rb 1 ;write operation type
|
||||
dma_seg rw 1 ;last dma segment
|
||||
dma_off rw 1 ;last dma offset
|
||||
hstbuf rb hstsiz ;host buffer
|
||||
end
|
||||
|
BIN
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/GENCMD.CMD
Normal file
BIN
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/GENCMD.CMD
Normal file
Binary file not shown.
BIN
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/GENCMD.COM
Normal file
BIN
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/GENCMD.COM
Normal file
Binary file not shown.
BIN
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/GENDEF.CMD
Normal file
BIN
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/GENDEF.CMD
Normal file
Binary file not shown.
BIN
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/GENDEF.COM
Normal file
BIN
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/GENDEF.COM
Normal file
Binary file not shown.
134
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDBDOS.H86
Normal file
134
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDBDOS.H86
Normal file
@@ -0,0 +1,134 @@
|
||||
:02000085000079
|
||||
:02000085000079
|
||||
:040000030000038076
|
||||
:1B03808131053F07F705440712129007490767076C0772077E078507EC034376
|
||||
:1B039B810EDA0D640EDE0EE40E0F0F130F140F1D0F1E0F1F0F200F260F2C0FF8
|
||||
:1B03B681330F4C09390F3F0F400F460F470F480F490F4A0F4B0F8B078B078777
|
||||
:1B03D1810F880F890FF10332053B0545054605460546054605460546053005A6
|
||||
:0B03EC81B022E99703BBA011E94A0B86
|
||||
:1B0400810000000000001E8CC88ED88F069D1180F905740580F90D7205C60685
|
||||
:1B041B81B111FF8C16941189269611803E98110174078CC88ED0BC59118B1E83
|
||||
:1B04368196118E069411268B5F0481E300027401FB8CD85557560E078C065DF6
|
||||
:1B04518110E81A005E5F5D8E065D10FA8E1694118B269611C606B111008E1E0D
|
||||
:1B046C819D11CF891699118816481032C0A39B11A25F10A24D10A24B10BB4CE3
|
||||
:1B0487810F5380F929720980E90680F9367201C38AD9B7008ACA03DB2EFFA7E6
|
||||
:1B04A2818003BB7610E819003C037555EB10BB8110EB08BB8D10EB03BB88101D
|
||||
:1B04BD81E80300E9700053E86701A0A4110441A27210B96610E8630159E85FE3
|
||||
:1B04D88101E96B001E5051C6065F10FF880E601032ED8B3699118936A911BF72
|
||||
:1B04F3819110893E99118E1E9D11FCF3A459581FC351B121EB0351B124E8CDEF
|
||||
:1B050E81FF59C30650518A0E601032ED8E069D11BE91108B3EA911893E9911D3
|
||||
:1B052981FCF3A4595807C3C3C3C3C606981100E9C80C8916A2118BCAE8EF0C23
|
||||
:1B054481C3C3C3BB1E108A07C607000AC07525E93F02E8EEFFE80A00721A505A
|
||||
:1B055F818AC8E8930058C33C0D740E3C0A740A3C0974063C0874023C20C3A051
|
||||
:1B057A811E100AC0751EE81702240174F1E80B023C13750DE804023C03740365
|
||||
:1B05958132C0C3E998FFA21E10B001C3A01B100AC0751651E8CDFF5951E8EEAC
|
||||
:1B05B081015951803EB611007403E8D301598AC1BB1D103C7F7416FE073C201A
|
||||
:1B05CB817310FE0F8A070AC074088AC13C087503FE0FC33C0A75FBC60700C310
|
||||
:1B05E6818AC1E87BFF730A50B15EE8AEFF5980C94080F90975A5B120E8A0FF85
|
||||
:1B060181A01D10240775F4C3E80500B120E88E01B108E98901B123E886FFE8AF
|
||||
:1B061C811000A01D103A061C1073E1B120E875FFEBF0B10DE86EFFB10AE9697D
|
||||
:1B063781FF8BF1AC3C2474C941518AC81E161FE8AEFF1F59EBEBA01D10A21CBE
|
||||
:1B065281108B1E9911268A0F4353B5005153E8E4FE5B593C0D7503E9C6003CD1
|
||||
:1B066D810A74F93C08750E0AED74E6FECDA01D10A21B10EB513C7F750C0AED8E
|
||||
:1B06888174D4268A07FECD4BEB7C3C05750C5153E893FFC6061C1000EBBE3C9D
|
||||
:1B06A381107506F616B611EBB23C1875145BA01C10BB1D10903A07739190FE71
|
||||
:1B06BE810FE847FFEBED3C157507E84BFF5BE97EFF3C12753551E83FFF595BA8
|
||||
:1B06D98153510AED740F43268A0FFECD5153E8FCFE5B59EBED53A01B100AC0A0
|
||||
:1B06F48174102A061D10A21B10E809FFFE0E1B1075F7EB9843268807FEC5519A
|
||||
:1B070F81538AC8E8D1FE5B59268A073C038AC5750B3C0175078CD88EC0E96DB8
|
||||
:1B072A81FE3AC17303E92CFF5B26882FB10D8CD88EC0E962FEE814FEEB44E8AE
|
||||
:1B074581CE0AEB3F8AC1FEC07409FEC0754CE84400EB30E83F000AC07503E978
|
||||
:1B0760811508E83000EB21E8CF0AEB1C8BCAE8CB0AC38BCA1E8E1E9D11E8BCAE
|
||||
:1B077B81FE1FC38E069D11E9C8FEE8F1FDA29B11C3B001EBF8BB0F12EB0DBB07
|
||||
:1B0796810912EB08BB0612EB03BB0C12FFD3C3FFD3CBBB0610FF2751B5008B65
|
||||
:1B07B181F28BFBFCF3A459C38A0EA411E85B0A83FB0074508B1783C302891E18
|
||||
:1B07CC81241083C302891E261083C302891E281083C30287DA891E41108B1EC7
|
||||
:1B07E7812A10891EAD11BB2A10B108E8B8FF8B162C10BB3210B10FE8ACFFA0BD
|
||||
:1B0802813810BB4A10C607FF0AC07403C60700B0FF0AC0C3E8FF0933C08B1E5B
|
||||
:1B081D8126108907C38B165210E8FE09EB078A0E4510E8F8090AC074DFBB0420
|
||||
:1B08388110E96FFF8B1EA611B102D3EB891E5210891E5710A15210BA0000F721
|
||||
:1B085381363210528BC88B362610890C030E3F10E8B809598B164110E8C20959
|
||||
:1B086E818BCBE9AE09BB34108A0FA05010D2E88AE8B1072A0FA04F10D2E00290
|
||||
:1B088981C5C38B1E991183C31003D9803E4A100074058A1FB700C303D98B1F8C
|
||||
:1B08A481C3E8CBFF8AC8B500E8DCFF891E5210C38B1E52100BDBC38A0E34101D
|
||||
:1B08BF818B1E5210D3E3891E5410A05010220635100AD8891E5210C38B1E9974
|
||||
:1B08DA811183C30C8A07C3BA0F0003169911BB110003DAC3E8F0FF8A07A25079
|
||||
:1B08F5811087DA8A07A24E10E8D7FFA036102207A24F10C3E8D5FFA047103CE5
|
||||
:1B09108102750232C002065010880787DAA04E108807C3B980008B1E2A1032EA
|
||||
:1B092B81C0020743E2FBC3518A0EA411BB0100D3E3590BD9C3A120108A0EA467
|
||||
:1B09468111D3E82401C38B0E2010E8DFFF891E20108B163910428B1E24108969
|
||||
:1B09618117C3E81B00BA090003DA8A07D0D0731BBB0A10EB08E8C7FF7411BB08
|
||||
:1B097C810810E92AFE8B1E2A10A05610B40003D8C38B1E991183C30E8A07C380
|
||||
:1B099781E8F3FFC60700C3E8ECFF0C808807C38B16A6118B1E24103B17C3E877
|
||||
:1B09B281F2FF72FA428917C3522BD38BDA5AC3B1FF8B1657108B1E3D10E8EC53
|
||||
:1B09CD81FF73E051E84FFF8B1E5710031E2E1059FEC1740D3A07740BE8BEFF48
|
||||
:1B09E8817306E85FFFC38807C3E8CDFFE81900B101E833FEEB06E80F00E81E31
|
||||
:1B0A0381FE8B0EA211E82808BBA011EB088CD9E81E08BB2A108B0FE907088B11
|
||||
:1B0A1E81162A108B1EA011B180068E069D11E87EFD07C3BBA6118A07433A0765
|
||||
:1B0A39817502FEC0C3BBFFFF891EA611C38B1639108B1EA61143891EA611E87C
|
||||
:1B0A548164FF7302EBE4A0A611240351B105D2E059A256100AC0750B51E8CC78
|
||||
:1B0A6F81FDE88BFF59E94CFFC3E806FF83C31051B1115AFEC97501C352803E6C
|
||||
:1B0A8A814A1000740851538A0FB500EB07FEC9518B0F43530BC974088B1E379E
|
||||
:1B0AA581103BD972005B4359EBD28B1E3710B103D3EB438BCB8B1E3010C607BA
|
||||
:1B0AC0810043E2FA8B163B108B1E30108917E845FD8B1E2410C7070300E862E4
|
||||
:1B0ADB81FFB1FFE865FFE84DFF743BE898FE803FE574EEA0A5113A07750C43C2
|
||||
:1B0AF6818A072C247505FEC8A29B11B101E872FFE8A8FEEBD1A04610E977FC4E
|
||||
:1B0B1181518A2E3610F6D522CD22C52AC1241F59C38B1E9911891E5910C606DF
|
||||
:1B0B2C814610FF880EA811C3E8EBFFE804FFE8D9FCC606651000B100E8FFFE75
|
||||
:1B0B4781E8E7FE7503E980008B1659108BF2AC3CE5740752E848FE5A73EBE875
|
||||
:1B0B62811DFE8A0EA811B5000AC974388BF2AC3C3F742980FD0D742480FD0C6B
|
||||
:1B0B7D8174082A07247F7533EB17518A0FE884FF599FF6066510FF7545C6069F
|
||||
:1B0B98816210009E759F4243FEC5FEC9EBC4C606461000A0A6112403A29B11F1
|
||||
:1B0BB3818AE8FEC5C30AED7530F607FF752BF6066210FF7424C6066510FFEB46
|
||||
:1B0BCE81CFE86CFEB0FF8AE8FEC5E9ADFB9E750E43803F0075088B36A6118954
|
||||
:1B0BE981366310E94EFFB100B22052B5008B16991103D1E882FD59E8AAFBE8B3
|
||||
:1B0C048136FCE9E8FDC3B10CE825FFE81FFE74F5B100B20CE8D8FFE81FFFEB3B
|
||||
:1B0C1F81EFB10FE80FFFE809FE74DFE8AAFC5053E84FFD87DA8B1E9911B12068
|
||||
:1B0C3A8152E86FFBE85DFD5ABB0C0003DA8A0FBB0F0003DA8A2F5B5888073AC5
|
||||
:1B0C55810F8AC57406B0007202B0808B1E9911BA0F0003DA8807C3833F007555
|
||||
:1B0C7081FA8BF2AD8907C333C0A29B11A3A611E8BEFC75F2E806FD248075EBDE
|
||||
:1B0C8B81B10FE8A4FEE89EFD74E1B91000E8E6FC03D987DA8B1E991103D9B1FB
|
||||
:1B0CA68110803E4A1000741B8A070AC08BF2AC750288070AC075068A078BFA16
|
||||
:1B0CC181FCAA3A077547EB16E8A0FF87DAE89BFF87DA8BF28B043B07753342F0
|
||||
:1B0CDC8143FEC94243FEC975C2B9ECFF03D987DA03D98BF2AC3A0772118807B6
|
||||
:1B0CF781B9030003D987DA03D98A078BFAFCAAC6064310FFE9F5FEFE0E9B111E
|
||||
:1B0D1281C332C0A24310E85CFFE813FD74F28B1E991183C30C8A07FEC0241FC3
|
||||
:1B0D2D818807740F8AE8A0361022C522064310740DEB1C83C302FE078A0724D4
|
||||
:1B0D48810F741CB10FE8E4FDE8DEFC7507A04410FEC0740BE8CBFEE88CFB3226
|
||||
:1B0D6381C0E921FAE822FAE931FCC606471001C6064410FFE874FBA050103A42
|
||||
:1B0D7E81064E1072183C807528E889FFE854FB33C0A350108807803E9B1100FC
|
||||
:1B0D99817514E807FBE813FB740CE815FBE8A3FAE876FAE95AFBE9DAF98B1E5D
|
||||
:1B0DB48122108A0EA411D3CB5387DAE8F7F95B7503E8E0F9D0DB72678B0E2227
|
||||
:1B0DCF8110E85FFB891E2210E9D5FCA04810A2A411EBD0E81FF7EB03E81FF7AF
|
||||
:1B0DEA818B1E9911C606611000F647088074098067087FC606611060C6064B79
|
||||
:1B0E058110FF8B1E99118A07241FFEC8A248103C1E7312A0A411A24C108A0798
|
||||
:1B0E2081A24D1024E08807E8B0FFA0A5118B1E99110807C3803E611060750787
|
||||
:1B0E3B818B1E9911C60700C3F7060210FFFF75048C0E021033DB891E20108998
|
||||
:1B0E56811E22108A1EB711881EA411E94EFFE87BFFE82DFB803EA51100740B4A
|
||||
:1B0E7181C7066410FE00C6066210FFE8A1FDE83C00F6066210FF7501C3C6064D
|
||||
:1B0E8C81621000813E6410FE0074F28B1E631080E3FC4B891EA611C606611060
|
||||
:1B0EA781608B1E9911C60700B10FE86EFCE886FCE86EFDE80100C3E870FB74ED
|
||||
:1B0EC281C65B803E61106075128B1E99118A470A24807507A26110B0FFEB4C16
|
||||
:1B0EDD81C3E801FFE993FDE81DF68B1E9D11891EAB11B1008B1E9911803F3F9E
|
||||
:1B0EF8817410E8DAF9803F3F7403E892FAE8E2FEB10FE827FCEB01C3E90AFB06
|
||||
:1B0F1381C3E8CBFEE81AFFE950FEC3C3C38B1E2210EB1BA0A411E95CF889163B
|
||||
:1B0F2E81A011E9D1FA8B1E3010EB088B1E2010EB02C3C3891E9B11C3C3C3C33B
|
||||
:1B0F4981C3C3C3803E4B100074248B1E9911803E6110607504804F0880C60793
|
||||
:1B0F648100A04D100AC0740B8807A04C10A24810E863FE803E5F10FF7503E851
|
||||
:0C0F7F8190F5A19B118BD8C3C3C3C3C3E1
|
||||
:02000086000078
|
||||
:1B100082A5070000A404B004B504BA04000000000000000000000000000000D4
|
||||
:1B101B8200000000E50000000000000000000000000000000000000000000053
|
||||
:1B1036820000000000000000000000000000000000000000000000000000001D
|
||||
:1B10518200000000000000000000000000000000000000000042646F73204515
|
||||
:1B106C827272204F6E20203A202442616420536563746F722453656C6563744D
|
||||
:0A1087822446696C6520522F4F2425
|
||||
:0B1194820000000000000000000000CE
|
||||
:1B11A082000000000000000000000000000000000000000000000000000000B2
|
||||
:0211BB820000B0
|
||||
:0111C88200A4
|
||||
:0211E08250003B
|
||||
:0111FA820072
|
||||
:00000001FF
|
||||
000000000000000000000000000D4
|
||||
:1B101B8200000000E50000000
|
690
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDBIOS.A86
Normal file
690
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDBIOS.A86
Normal file
@@ -0,0 +1,690 @@
|
||||
title '8086 Disk I/O Drivers'
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* Basic Input/Output System (BIOS) for *
|
||||
;* CP/M-86 Configured for iSBC 86/12 with *
|
||||
;* the iSBC 204 Floppy Disk Controller *
|
||||
;* *
|
||||
;* (Note: this file contains both embedded *
|
||||
;* tabs and blanks to minimize the list file *
|
||||
;* width for printing purposes. You may wish*
|
||||
;* to expand the blanks before performing *
|
||||
;* major editing.) *
|
||||
;*********************************************
|
||||
|
||||
; 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
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* Loader_bios is true if assembling the *
|
||||
;* LOADER BIOS, otherwise BIOS is for the *
|
||||
;* CPM.SYS file. Blc_list is true if we *
|
||||
;* have a serial printer attached to BLC8538 *
|
||||
;* Bdos_int is interrupt used for earlier *
|
||||
;* versions. *
|
||||
;* *
|
||||
;*********************************************
|
||||
|
||||
loader_bios equ true
|
||||
blc_list equ true
|
||||
bdos_int equ 224 ;reserved BDOS Interrupt
|
||||
|
||||
IF not loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
bios_code equ 2500h
|
||||
ccp_offset equ 0000h
|
||||
bdos_ofst equ 0B06h ;BDOS entry point
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;not loader_bios
|
||||
|
||||
IF loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
bios_code equ 1200h ;start of LDBIOS
|
||||
ccp_offset equ 0003h ;base of CPMLOADER
|
||||
bdos_ofst equ 0406h ;stripped BDOS entry
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;loader_bios
|
||||
|
||||
csts equ 0DAh ;i8251 status port
|
||||
cdata equ 0D8h ; " data port
|
||||
|
||||
IF blc_list
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
lsts equ 41h ;2651 No. 0 on BLC8538 status port
|
||||
ldata equ 40h ; " " " " " data port
|
||||
blc_reset equ 60h ;reset selected USARTS on BLC8538
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;blc_list
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* 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)
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* INIT Entry Point, Differs for LDBIOS and *
|
||||
;* BIOS, according to "Loader_Bios" value *
|
||||
;* *
|
||||
;*********************************************
|
||||
|
||||
INIT: ;print signon message and initialize hardware
|
||||
mov ax,cs ;we entered with a JMPF so use
|
||||
mov ss,ax ; CS: as the initial value of SS:,
|
||||
mov ds,ax ; DS:,
|
||||
mov es,ax ; and ES:
|
||||
;use local stack during initialization
|
||||
mov sp,offset stkbase
|
||||
cld ;set forward direction
|
||||
|
||||
IF not loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
; This is a BIOS for the CPM.SYS file.
|
||||
; Setup all interrupt vectors in low
|
||||
; memory to address trap
|
||||
|
||||
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
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* National "BLC 8538" Channel 0 for a serial*
|
||||
;* 9600 baud printer - this board uses 8 Sig-*
|
||||
;* netics 2651 Usarts which have on-chip baud*
|
||||
;* rate generators. *
|
||||
;* *
|
||||
;*********************************************
|
||||
|
||||
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
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;not loader_bios
|
||||
|
||||
IF loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
;This is a BIOS for the LOADER
|
||||
push ds ;save data segment
|
||||
mov ax,0
|
||||
mov ds,ax ;point to segment zero
|
||||
;BDOS interrupt offset
|
||||
mov bdos_offset,bdos_ofst
|
||||
mov bdos_segment,CS ;bdos interrupt segment
|
||||
pop ds ;restore data segment
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;loader_bios
|
||||
|
||||
mov bx,offset signon
|
||||
call pmsg ;print signon message
|
||||
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
|
||||
|
||||
IF not loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
int_trap:
|
||||
cli ;block interrupts
|
||||
mov ax,cs
|
||||
mov ds,ax ;get our data segment
|
||||
mov bx,offset int_trp
|
||||
call pmsg
|
||||
hlt ;hardstop
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;not loader_bios
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* 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
|
||||
|
||||
IF blc_list
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
call LISTST
|
||||
jz LISTOUT ;wait for printer not busy
|
||||
mov al,cl
|
||||
out ldata,al ;send char to TI 810
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;blc_list
|
||||
|
||||
ret
|
||||
|
||||
LISTST: ;poll list status
|
||||
|
||||
IF blc_list
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
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
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;blc_list
|
||||
|
||||
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 bx,0000h
|
||||
cmp cl,2 ;this BIOS only supports 2 disks
|
||||
jnb return ;return w/ 0000 in BX if bad drive
|
||||
mov al, 80h
|
||||
cmp cl,0
|
||||
jne sel1 ;drive 1 if not zero
|
||||
mov al, 40h ;else drive is 0
|
||||
sel1: mov sel_mask,al ;save drive select mask
|
||||
;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
|
||||
;create offset from Disk Parameter Base
|
||||
add bx,offset dp_base
|
||||
return:
|
||||
ret
|
||||
|
||||
HOME: ;move selected disk to home position (Track 0)
|
||||
mov trk,0 ;set disk i/o to track zero
|
||||
mov bx,offset hom_com
|
||||
call execute
|
||||
jz return ;home drive and return if OK
|
||||
mov bx,offset bad_hom ;else print
|
||||
call pmsg ;"Home Error"
|
||||
jmps home ;and retry
|
||||
|
||||
SETTRK: ;set track address given by CX
|
||||
mov trk,cl ;we only use 8 bits of track address
|
||||
ret
|
||||
|
||||
SETSEC: ;set sector number given by cx
|
||||
mov sect,cl ;we only use 8 bits of sector address
|
||||
ret
|
||||
|
||||
SECTRAN: ;translate sector CX using table at [DX]
|
||||
mov bx,cx
|
||||
add bx,dx ;add sector to tran table address
|
||||
mov bl,[bx] ;get logical sector
|
||||
ret
|
||||
|
||||
SETDMA: ;set DMA offset given by CX
|
||||
mov dma_adr,CX
|
||||
ret
|
||||
|
||||
SETDMAB: ;set DMA segment given by CX
|
||||
mov dma_seg,CX
|
||||
ret
|
||||
;
|
||||
GETSEGT: ;return address of physical memory table
|
||||
mov bx,offset seg_table
|
||||
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:
|
||||
mov al,12h ;basic read sector command
|
||||
jmps r_w_common
|
||||
|
||||
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 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
|
||||
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
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* 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,12h
|
||||
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,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 segment address
|
||||
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 ;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
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* Data Areas *
|
||||
;* *
|
||||
;*********************************************
|
||||
data_offset equ offset $
|
||||
|
||||
dseg
|
||||
org data_offset ;contiguous with code segment
|
||||
|
||||
IF loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
signon db cr,lf,cr,lf
|
||||
db 'CP/M-86 Version 1.1',cr,lf,0
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;loader_bios
|
||||
|
||||
IF not loader_bios
|
||||
;---------------------------------------------
|
||||
;| |
|
||||
signon db cr,lf,cr,lf
|
||||
db ' System Generated - 11 Jan 81',cr,lf,0
|
||||
;| |
|
||||
;---------------------------------------------
|
||||
ENDIF ;not loader_bios
|
||||
|
||||
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,'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
|
||||
|
||||
; 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 2000h ;second is 20000 -
|
||||
dw 2000h ;3FFFF (128k)
|
||||
|
||||
include singles.lib ;read in disk definitions
|
||||
|
||||
loc_stk rw 32 ;local stack for initialization
|
||||
stkbase equ offset $
|
||||
|
||||
lastoff equ offset $
|
||||
tpa_seg equ (lastoff+0400h+15) / 16
|
||||
tpa_len equ 0800h - tpa_seg
|
||||
db 0 ;fill last address for GENCMD
|
||||
|
||||
;*********************************************
|
||||
;* *
|
||||
;* Dummy Data Section *
|
||||
;* *
|
||||
;*********************************************
|
||||
dseg 0 ;absolute low memory
|
||||
org 0 ;(interrupt vectors)
|
||||
int0_offset rw 1
|
||||
int0_segment rw 1
|
||||
; pad to system call vector
|
||||
rw 2*(bdos_int-1)
|
||||
|
||||
bdos_offset rw 1
|
||||
bdos_segment rw 1
|
||||
END
|
||||
|
41
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDBIOS.H86
Normal file
41
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDBIOS.H86
Normal file
@@ -0,0 +1,41 @@
|
||||
:0400000300001200E7
|
||||
:1B120081E93C00E96100E96100E96700E96E00E97600E98800E98500E9D000FB
|
||||
:1B121B81E9AC00E9DF00E9E100E9EA00E9F500E9F600E96200E9D700E9E000AC
|
||||
:1B123681E9E200E96400E964008CC88ED08ED88EC0BCA916FC1EB800008ED89E
|
||||
:1B125181C706800306048C0E82031FBB1514E85A00B100E99CEDE99FEDE4DAED
|
||||
:1B126C81240274020CFFC3E8F4FF74FBE4D8247FC3E4DA240174FA8AC1E6D8B6
|
||||
:1B128781C3E8070074FB8AC1E640C3E44124813C81750A0CFFC3B01AC3B00065
|
||||
:1B12A281C3C32400C3E8C9FF508AC8E8CDFF583C6172063C7A77022C20C38A08
|
||||
:1B12BD810784C074288AC8E8B6FF43EBF2BB000080F9027318B08080F90075C0
|
||||
:1B12D88102B040A22E15B5008BD9B104D3E381C34115C3C606311500BB3315AD
|
||||
:1B12F381E8350074F2BB2F14E8BEFFEBEB880E3115C3880E3215C38BD903DAE3
|
||||
:1B130E818A1FC3890E2A15C3890E2C15C3BB3815C3B012EB02B00ABB2F1588E8
|
||||
:1B1329814701891E2815C60627150A8B1E2815E889008B1E28158A4701B90022
|
||||
:1B134481083C2C720BB98080240F3C0CB0007736E4A022C532C174F8E4A1241C
|
||||
:1B135F811E74283C107425FE0E271575C8B4008BD88B9F5614E845FFE4D8E853
|
||||
:1B137A812BFF3C4374253C5274AB3C49741A0CFFC3E81A0075A4E81500759FDB
|
||||
:1B139581BBC714E821FFE80A0074FBEB922400C3E9BFFEB640F6062E15807589
|
||||
:1B13B08102B604BB3615E80B00E4A0A88075FAE4A184C6C3E4A0A88075FA8A9A
|
||||
:1B13CB8147013C127504B140EB063C0A7520B180B004E6A8B000E6A58AC1E6DB
|
||||
:1B13E681A5A12A15E6A48AC4E6A4A12C15E6AA8AC4E6AA8A0F438A070A062E89
|
||||
:1414018115E6A0FEC9748243E4A0A82075FA8A07E6A1EBEF0E
|
||||
:1B1415820D0A0D0A43502F4D2D38362056657273696F6E20312E310D0A000D88
|
||||
:1B1430820A486F6D65204572726F720D0A000D0A496E746572727570742054F3
|
||||
:1B144B827261702048616C740D0A00761476147614761486149614A314B41416
|
||||
:1B146682C714DB14ED14021512157614761476140D0A4E756C6C204572726FD8
|
||||
:1B14818272203F3F000D0A436C6F636B204572726F72203A000D0A4C6174659A
|
||||
:1B149C8220444D41203A000D0A494420435243204572726F72203A000D0A44EC
|
||||
:1B14B78261746120435243204572726F72203A000D0A4472697665204E6F7484
|
||||
:1B14D282205265616479203A000D0A57726974652050726F74656374203A0091
|
||||
:1B14ED820D0A54726B203030204E6F7420466F756E64203A000D0A5772697416
|
||||
:1B15088265204661756C74203A000D0A536563746F72204E6F7420466F756EDB
|
||||
:1B15238264203A00000000000000004003000000022900012C02AB01550600C9
|
||||
:1B153E8220002070150000000000008A15611529160A16701500000000000052
|
||||
:1B1559828A156115581639161A00030700F2003F00C0001000020001070D13D4
|
||||
:1615748219050B111703090F1502080E141A060C1218040A1016A8
|
||||
:0116688200FF
|
||||
:0116A98200BE
|
||||
:02000086000078
|
||||
:00000001FF
|
||||
2205265616479203A000D0A57726974652050726F74656374203A0091
|
||||
:1B14ED820D0A54726B203030204E6F742046
|
508
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDCOPY.A86
Normal file
508
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDCOPY.A86
Normal file
@@ -0,0 +1,508 @@
|
||||
title 'LDCOPY Ver 1.1 Oct 81'
|
||||
|
||||
vers equ 10
|
||||
|
||||
; Copyright, (C) 1981
|
||||
; Digital Research, Inc.
|
||||
; P.O. Box 579
|
||||
; Pacific Grove, CA 93950
|
||||
|
||||
|
||||
; LDCOPY is used to generate and propagate bootable CP/M-86 systems.
|
||||
|
||||
; It copies a CP/M-86 Loader image (either from a disk file, or from
|
||||
; the system tracks of an existing CP/M-86 system diskette) to a new
|
||||
; diskette.
|
||||
|
||||
; The following equates will require modification for different
|
||||
; diskette formats. For convienence, they are only referenced
|
||||
; by a pair of data bytes near the end of the data segment.
|
||||
; In addition, the skew table in the data area will need modification.
|
||||
|
||||
sdspt equ 26 ; number of sectors per track
|
||||
sdlt equ 2 ; " of tracks for loader
|
||||
|
||||
|
||||
|
||||
; **************************
|
||||
; *
|
||||
; * global equates
|
||||
; *
|
||||
; **************************
|
||||
|
||||
bdosint equ 224 ;BDOS interrupt number
|
||||
|
||||
false equ 0
|
||||
true equ not false
|
||||
cr equ 0dh ;carriage return
|
||||
lf equ 0ah ;line feed
|
||||
|
||||
|
||||
sdndisks equ 16 ; maximum number of drives
|
||||
sdsecsiz equ 128 ; size of each sector
|
||||
|
||||
tpa equ 100h
|
||||
fcbaddr equ 5ch
|
||||
fcbname equ fcbaddr + 1 ;1st char of file name
|
||||
fcbtype equ fcbaddr + 9 ;file type
|
||||
fcbcr equ fcbaddr + 32 ;current record
|
||||
|
||||
cseg
|
||||
|
||||
jmp start
|
||||
db ' COPYRIGHT (C) 1981, DIGITAL RESEARCH '
|
||||
|
||||
Rs 100H ; Emergency patch area
|
||||
|
||||
; ***********************
|
||||
; *
|
||||
; * program begins here
|
||||
; *
|
||||
; ***********************
|
||||
|
||||
start:
|
||||
mov ax,ds
|
||||
mov es,ax
|
||||
|
||||
mov dx,offset signon
|
||||
call outmsg
|
||||
cmp byte ptr .fcbname,' '
|
||||
jz gl ;check for file given on command line
|
||||
call getfile ;read ldr from file
|
||||
jmp ps
|
||||
gl: call getldr ;read ldr from 1st 2 tracks
|
||||
ps: call putldr ;put ldr on " " "
|
||||
jmp reboot
|
||||
|
||||
; ***************************
|
||||
; *
|
||||
; * getfile: get the file specified in command tail into ram
|
||||
; *
|
||||
; ***************************
|
||||
|
||||
getfile:
|
||||
cmp byte ptr .fcbtype,' '
|
||||
jnz opn
|
||||
mov byte ptr .fcbtype, 'C'
|
||||
mov byte ptr .fcbtype + 1,'M'
|
||||
mov byte ptr .fcbtype + 2,'D'
|
||||
opn:
|
||||
mov dx,fcbaddr ;try to open it
|
||||
call open
|
||||
inc al ;255 becomes 00
|
||||
jnz rdok ;ok to read if not 255
|
||||
|
||||
mov dx,offset nofile
|
||||
call crmsg ;file not present, error and reboot
|
||||
jmp reboot
|
||||
rdok:
|
||||
mov byte ptr .fcbcr,0 ;current record = 0
|
||||
mov dx,offset loadp ;base of buffer
|
||||
mov cx,maxsecs ;sector count
|
||||
rdinp:
|
||||
push cx
|
||||
push dx ;ready for dma
|
||||
call bdma ;bdos dma function
|
||||
mov dx,fcbaddr ;ready for read
|
||||
call dread
|
||||
pop dx ;recall dma address
|
||||
pop cx ;recall sector count
|
||||
cmp al,1 ;check for eof
|
||||
jz don
|
||||
dec cx ;don't read to far
|
||||
jz don
|
||||
or al,al ;0 if read ok
|
||||
jnz badrd
|
||||
add dx,secsiz ;inc dma by sector size
|
||||
jmp rdinp
|
||||
don:
|
||||
ret
|
||||
badrd: ;read error encountered in input file
|
||||
mov dx,offset badfile
|
||||
call crmsg
|
||||
jmp reboot
|
||||
|
||||
; **************************
|
||||
; *
|
||||
; * getldr: get CP/M loader from 1st N tracks
|
||||
; *
|
||||
; **************************
|
||||
|
||||
getldr:
|
||||
mov dx,offset askget
|
||||
call crmsg ;which drive is source on ?
|
||||
call getchar ;must get from disk - not from memory
|
||||
mov ah,al ;save ascii char
|
||||
sub al,'A' ;normalize drive number
|
||||
cmp al,ndisks ;valid drive?
|
||||
jb getc ;skip to getc if so
|
||||
call baddisk ;invalid drive number
|
||||
jmp getldr ;to try again
|
||||
getc:
|
||||
mov gdisk,ah ;ascii drive letter for message
|
||||
call sel ;to select the drive in al
|
||||
call crlf
|
||||
mov dx,offset getmsg
|
||||
call outmsg ;make sure right drive
|
||||
call getchar
|
||||
cmp al,cr ;user mistake, no cr
|
||||
jnz gboot
|
||||
call crlf
|
||||
mov rewr,0 ;set to read for getput
|
||||
call getput
|
||||
mov dx,offset done
|
||||
call outmsg
|
||||
ret
|
||||
gboot: jmp reboot ;back to cp/m
|
||||
|
||||
; *******************************
|
||||
; *
|
||||
; * putldr: put CP/M loader on 1st N tracks
|
||||
; *
|
||||
; *******************************
|
||||
|
||||
putldr:
|
||||
mov dx,offset askput
|
||||
call crmsg ;what drive to put ldr
|
||||
call getchar
|
||||
cmp al,cr ;all done if cr
|
||||
jz pboot ;this is normal program exit point
|
||||
mov ah,al ;save ascii drive letter
|
||||
sub al,'A' ;make it a number
|
||||
cmp al,ndisks
|
||||
jb putc
|
||||
call baddisk ;invalid drive name
|
||||
jmp putldr ;to try again
|
||||
putc:
|
||||
mov pdisk,ah ;drive letter in message
|
||||
call sel ;select dest drive in al
|
||||
mov dx,offset putmsg
|
||||
call crmsg ;check with user for ok
|
||||
call getchar
|
||||
cmp al,cr ;user mistake if not cr, reboot
|
||||
jnz pboot
|
||||
call crlf
|
||||
mov rewr,1 ;set to write for getput
|
||||
call getput ;to put loader back on diskette
|
||||
mov dx,offset done
|
||||
call outmsg
|
||||
jmp putldr ;for another put operation
|
||||
pboot: jmp reboot ;back to cp/m
|
||||
|
||||
; ***********************
|
||||
; *
|
||||
; * getput: get or put loader (rewr=0 for read, 1 for write)
|
||||
; * disk is already selected
|
||||
; *
|
||||
; ***********************
|
||||
|
||||
getput:
|
||||
mov bx,offset loadp ;load point in ram for cp/m during LDCOPY
|
||||
mov dmaddr,bx
|
||||
;clear track to 00
|
||||
mov track,-1 ;start with track equal -1
|
||||
rwtrk: ;read or write next track
|
||||
inc track ;track = track + 1
|
||||
mov cx,track
|
||||
cmp cx,nlt ;number of loader tracks = current track ?
|
||||
jnz nxttrk ;end of this routine > 128 bytes
|
||||
jmp endrw ;end of read or write
|
||||
;otherwise notdone, go to next track
|
||||
nxttrk:
|
||||
mov cx,track
|
||||
call trk ;to set track
|
||||
mov sector,-1 ;counts 0, 1, 2, . . . 25
|
||||
;sector incremented before read or write
|
||||
rwsec: ;read or write sector
|
||||
inc sector ;to next sector
|
||||
mov bx,sector ;current sector
|
||||
cmp bx,spt ;sectors per track
|
||||
jz endtrk
|
||||
;read or write sector to or from
|
||||
l_5: ;current dma address
|
||||
mov si,offset tran
|
||||
add bx,bx ; double sector number
|
||||
mov cx,[bx+si] ;xlate to physical sector
|
||||
push si
|
||||
push cx
|
||||
call sec ;set up sector number
|
||||
pop cx
|
||||
pop si
|
||||
mov bx,[si]
|
||||
sub cx,bx ;tran(sector)-tran(0)
|
||||
call multsec ;cx * sector size
|
||||
add cx,dmaddr ;base of dma for this track
|
||||
;+(tran(sector)-tran(0))*secsiz
|
||||
call dma ;dma address set from cx
|
||||
;dma address set, clear retry count
|
||||
trysec: ;try to read or write current sector
|
||||
Mov Cl, 00
|
||||
Mov Ax, Track
|
||||
Inc Ax
|
||||
Cmp Ax, Nlt
|
||||
Jne Normal_Write
|
||||
|
||||
Mov Ax, Sector
|
||||
Inc Ax
|
||||
Cmp Ax, Spt
|
||||
Jne Normal_Write
|
||||
Mov Cl, 01
|
||||
Normal_Write:
|
||||
or rewr,0 ;read or write?
|
||||
jz tryread
|
||||
;must be write
|
||||
call write
|
||||
jmp chkrw ;check for error returns
|
||||
tryread:
|
||||
call read
|
||||
chkrw:
|
||||
or al,al
|
||||
jz rwsec
|
||||
|
||||
mov dx,offset errmsg
|
||||
call outmsg
|
||||
call getchar
|
||||
cmp al,cr
|
||||
jne reboot1 ;local jmp then to reboot, >128
|
||||
;typed a cr, ok to ignore
|
||||
call crlf
|
||||
jmp rwsec
|
||||
|
||||
endtrk: ;end of track
|
||||
mov cx,spt ;sectors per track
|
||||
call multsec ;*secsiz
|
||||
mov bx,dmaddr ;base dma for this track
|
||||
add bx,cx
|
||||
;+ spt * secsiz
|
||||
mov dmaddr,bx ;ready for next track
|
||||
jmp rwtrk ;for another track
|
||||
|
||||
endrw: ;end of read or write, return to caller
|
||||
ret
|
||||
|
||||
reboot1:jmp reboot ;farther than 128 bytes
|
||||
|
||||
; *****************************************
|
||||
; *
|
||||
; * utility subroutines
|
||||
; *
|
||||
; ****************************************
|
||||
;
|
||||
;*****
|
||||
multsec: ;cx * sector size
|
||||
push dx ;return value in cx
|
||||
mov ax,secsiz
|
||||
mul cx
|
||||
mov cx,ax
|
||||
pop dx
|
||||
ret
|
||||
;*****
|
||||
baddisk:
|
||||
mov dx,offset qdisk ;bad disk name
|
||||
call crmsg
|
||||
ret
|
||||
|
||||
; **********************
|
||||
; *
|
||||
; * bdos subroutines
|
||||
; *
|
||||
; **********************
|
||||
|
||||
bdos: int bdosint
|
||||
ret
|
||||
;function numbers in cl
|
||||
|
||||
reset equ 0 ;warm boot
|
||||
coni equ 1 ;console input
|
||||
cono equ 2 ;console output
|
||||
prstr equ 9 ;print string
|
||||
rconb equ 10 ;read console buffer
|
||||
self equ 14 ;select disk
|
||||
openf equ 15 ;disk open
|
||||
setdmaf equ 26 ;where data will go
|
||||
dreadf equ 20 ;disk read
|
||||
biosf equ 50 ;bios call
|
||||
|
||||
reboot:
|
||||
mov al,0
|
||||
call sel
|
||||
call crlf
|
||||
mov cl,reset
|
||||
mov dl,0 ; release memory
|
||||
jmp bdos
|
||||
;****
|
||||
getchar: ;get an upper case char into al
|
||||
call getbuf ;use buffered console read
|
||||
cmp conbuf+1,0 ;just a crlf?
|
||||
mov al,cr
|
||||
jz ex
|
||||
mov al,conbuf+2 ;first char read
|
||||
cmp al,'a' ;translate to upper case if lower
|
||||
jb ex
|
||||
cmp al,'z'
|
||||
ja ex
|
||||
and al,5fh ;it is lower, make upper
|
||||
ex: ret
|
||||
;****
|
||||
getbuf:
|
||||
;read console buffer
|
||||
mov cl,rconb
|
||||
mov dx,offset conbuf
|
||||
jmp bdos
|
||||
;****
|
||||
putchar:
|
||||
;write character from al to console
|
||||
mov dl,al
|
||||
mov cl,cono
|
||||
jmp bdos
|
||||
;****
|
||||
crlf: ;send carriage return, line feed
|
||||
mov al,cr
|
||||
call putchar
|
||||
mov al,lf
|
||||
call putchar
|
||||
ret
|
||||
;****
|
||||
crmsg: ;print message addressed by dx til zero
|
||||
;with leading crlf
|
||||
push dx
|
||||
call crlf
|
||||
pop dx ;drop thru to outmsg0
|
||||
;****
|
||||
outmsg:
|
||||
mov cl,prstr
|
||||
jmp bdos ;dx has string addr
|
||||
;****
|
||||
bdma: ;dx has address
|
||||
mov cl,setdmaf
|
||||
jmp bdos
|
||||
;****
|
||||
dread: ;disk read function
|
||||
mov cl,dreadf
|
||||
jmp bdos
|
||||
;****
|
||||
open: ;file open function
|
||||
mov cl,openf
|
||||
jmp bdos
|
||||
;****
|
||||
bios:
|
||||
mov fnum,al ;bios function number
|
||||
mov bcx,cx
|
||||
mov bdx,dx
|
||||
mov dx,offset(bds)
|
||||
mov cl,biosf
|
||||
jmp bdos
|
||||
|
||||
; ****************************
|
||||
; *
|
||||
; * bios utilities
|
||||
; *
|
||||
; ****************************
|
||||
|
||||
seldsk equ 9 ;wboot+24 for disk select
|
||||
settrk equ 10 ;wboot+27 for set track function
|
||||
setsec equ 11 ;wboot+30 for set sector function
|
||||
setdma equ 12 ;wboot+33 for set dma address
|
||||
readf equ 13 ;wboot+36 for read function
|
||||
writf equ 14 ;wboot+39 for write function
|
||||
|
||||
sel:
|
||||
;select disk given by register a
|
||||
mov cl,al
|
||||
mov al,seldsk
|
||||
jmp bios
|
||||
;****
|
||||
trk: ;set up track
|
||||
mov al,settrk ;offset for settrk entry
|
||||
jmp bios ;gone to settrk
|
||||
;****
|
||||
sec: ;set up sector number
|
||||
mov al,setsec
|
||||
jmp bios
|
||||
;****
|
||||
dma: ;set dma address to value of cx
|
||||
mov al,setdma
|
||||
jmp bios
|
||||
;****
|
||||
read: ;perform read operation
|
||||
mov al,readf
|
||||
jmp bios
|
||||
;****
|
||||
write: ;perform write operaton
|
||||
mov al,writf
|
||||
jmp bios
|
||||
|
||||
; **************************
|
||||
; *
|
||||
; * data areas
|
||||
; *
|
||||
; **************************
|
||||
|
||||
|
||||
dseg
|
||||
org 0100h ; skip past page zero
|
||||
;messages
|
||||
|
||||
signon db 'LDCOPY VERS '
|
||||
db vers/10+'0','.',vers mod 10+'0','$'
|
||||
askget db 'Source Drive Name $'
|
||||
getmsg db 'Source On '
|
||||
gdisk rs 1 ;filled in at get function
|
||||
db ', Then Type Return$'
|
||||
askput db 'Destination Drive Name (Or Return To Reboot) $'
|
||||
putmsg db 'Destination On '
|
||||
pdisk rs 1 ;filled in at put function
|
||||
db ', Then Type Return$'
|
||||
errmsg db 'Permanent Error, Type Return To Ignore$'
|
||||
done db 'Function Complete$'
|
||||
qdisk db 'Invalid Drive Name$'
|
||||
nofile db 'No Source File On Disk$'
|
||||
badfile db 'Source File Read Error$'
|
||||
|
||||
;translate table
|
||||
|
||||
tran dw 1,3,5,7,9,11,13,15,17,19,21,23,25
|
||||
dw 2,4,6,8,10,12,14,16,18,20,22,24,26
|
||||
|
||||
;leave room for double density
|
||||
dw 0,0,0,0,0,0,0,0
|
||||
dw 0,0,0,0,0,0,0,0
|
||||
dw 0,0,0,0,0,0,0,0
|
||||
dw 0,0,0,0,0,0,0,0 ; (64 extra bytes reserved)
|
||||
|
||||
|
||||
; *************************
|
||||
; *
|
||||
; * variables
|
||||
; *
|
||||
; ************************
|
||||
|
||||
|
||||
bds: ;bios data structure
|
||||
fnum rb 1 ;storage for bios parameters
|
||||
bcx rw 1 ;the bdos bios func puts these
|
||||
bdx rw 1 ;in registers before jumping to bios
|
||||
|
||||
|
||||
nlt dw sdlt ;number of loader tracks
|
||||
spt dw sdspt ;sectors per track
|
||||
|
||||
ndisks db sdndisks ;number of disks
|
||||
secsiz dw sdsecsiz ;sector size
|
||||
maxsecs dw sdlt * sdspt ;maximum sectors to read from file
|
||||
sdisk rb 1 ;selected disk for current operation
|
||||
track rw 1 ;current track
|
||||
rewr rb 1 ;read if 0,write if 1
|
||||
sector rw 1 ;current sector
|
||||
dmaddr dw 0 ;current dma address
|
||||
retry rb 1 ;number of tries on this sector
|
||||
conbuf db 30
|
||||
rb 32 ;console buffer
|
||||
;make stack on even address
|
||||
|
||||
loadp rs sdsecsiz*sdspt*sdlt
|
||||
|
||||
db 0 ; force out last data segement byte
|
||||
|
||||
end
|
||||
|
240
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDCPM.A86
Normal file
240
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDCPM.A86
Normal file
@@ -0,0 +1,240 @@
|
||||
title 'CP/M-86 Loader'
|
||||
|
||||
; The CPMLDR consists of this module along with the
|
||||
; LDRBDOS and LBIOS.
|
||||
|
||||
; CPMLDR resides on the first two tracks of a
|
||||
; CP/M-86 system diskette and is brought into memory
|
||||
; by the ROM bootstrap loader to load initiate CP/M-86
|
||||
|
||||
; It opens the file 'CPM.SYS' using the LDRBDOS and LBIOS
|
||||
; and then reads it into memory. Finally, a jump to the BIOS
|
||||
; initialization entry point starts CP/M-86
|
||||
|
||||
; The first 128 byte record of the CPM.SYS file is a header
|
||||
; with the following format:
|
||||
|
||||
; ty rb 1 ;seg type (not used here)
|
||||
; len rw 1 ;length (not used here)
|
||||
; abs dw ldrstart ;absolute segment address for LOADER
|
||||
; min rw 1 ;minimum mem (not used here)
|
||||
; max rw 1 ;max mem needed (not used here)
|
||||
|
||||
; (This header record is constructed automatically by the
|
||||
; GENCMD utility).
|
||||
|
||||
; CPMLDR may be read into any segment that does not
|
||||
; overlap the desired system load segment as it makes
|
||||
; all memory references using copies of the CS: register
|
||||
; it is entered with.
|
||||
|
||||
false equ 0
|
||||
true equ not false
|
||||
|
||||
cr equ 0dh
|
||||
lf equ 0ah
|
||||
|
||||
lbios_offset equ 1200h ; offset of LBIOS
|
||||
|
||||
biosoff equ 2500h ; offset of BIOS from start of CPM.SYS
|
||||
; this is the entry point into CPM.SYS
|
||||
|
||||
bootdrv equ 0 ; boot drive always zero
|
||||
|
||||
; 128 bytes of CPM.SYS
|
||||
|
||||
lbdosoff equ 406H ;location of LBDOS in LOADER
|
||||
|
||||
bdos_int equ 224 ;lbdos interrupt number
|
||||
|
||||
; dummy section for interrupt vectors
|
||||
|
||||
dseg 0
|
||||
org 0
|
||||
abs_zero rw 2*bdosint
|
||||
bdos_offset rw 1
|
||||
bdos_segment rw 1
|
||||
|
||||
; bdos function numbers
|
||||
|
||||
coutf equ 2
|
||||
pstrf equ 9
|
||||
seldsk equ 14
|
||||
openf equ 15
|
||||
readsf equ 20
|
||||
dmaf equ 26
|
||||
dmabf equ 51
|
||||
|
||||
|
||||
;*******************************
|
||||
;*
|
||||
;* CPMLDR starts here
|
||||
;*
|
||||
;*******************************
|
||||
|
||||
cseg
|
||||
org 0 ; JMPF to here from boot ROM
|
||||
|
||||
jmp LBIOS ; allow loader BIOS to
|
||||
; initialize
|
||||
start: ; loader BIOS jumps here
|
||||
|
||||
xor ax,ax ! mov ds,ax ; temp DS at absolute zero
|
||||
mov bdos_offset,lbdosoff ; to patch in interrupt table
|
||||
mov bdos_segment,cs ; offset and segment
|
||||
mov ax,cs ! mov ss,ax ; make ss, ds, es = cs
|
||||
mov ds,ax ! mov es,ax
|
||||
mov sp,offset(stack) ; set up local stack
|
||||
|
||||
call initlbdos ;warm up lbdos and lbios
|
||||
call openfnc ;open CPM.SYS
|
||||
cmp al,255 ! jne perr ; insure good file
|
||||
mov dx,offset nofile ! call msg ; no CPM.SYS file
|
||||
jmp stop ; then halt the machine
|
||||
perr:
|
||||
mov dx,cs ! call setdmab
|
||||
mov dx,offset page1 ! call setdma ;read first page of CPM.SYS
|
||||
call read
|
||||
mov ax,word ptr page1+3 ;get abs field from header
|
||||
mov ldseg,ax ; save it and
|
||||
mov dx,ax ! call setdmab ; set DMA segment for disk IO
|
||||
mov dx,offset segment ! call msg ; put memory map on console
|
||||
mov ax,ldseg ! call phex ; print base system segment
|
||||
|
||||
;
|
||||
mov dx,0 ;offset of CPM in segment
|
||||
readit:
|
||||
call setdma ; set DMA offset for
|
||||
push dx ! call read ; next sector read
|
||||
cmp al,01H ! je done ; check for EOF
|
||||
cmp al,0 ! je prerr ; check for good write
|
||||
mov dx,offset rerr ! call msg ; print READ ERROR message
|
||||
jmp stop ; hard stop on any error
|
||||
|
||||
prerr: pop dx ! add dx,80h ; address for next record
|
||||
jmp readit
|
||||
done:
|
||||
mov dx,offset lenmsg ! call msg ; print length message
|
||||
pop ax ! dec ax ! call phex ; print last address
|
||||
call pcrlf ; and a crlf
|
||||
jmpf bios ; leap to BIOS initialization
|
||||
|
||||
;*****************************
|
||||
;*
|
||||
;* subroutines
|
||||
;*
|
||||
;*****************************
|
||||
|
||||
;******
|
||||
phex: ;print 4 hex characters from ax
|
||||
mov cx,0404h ; 4 in both CH and CL
|
||||
lhex:
|
||||
rol ax,cl ; rotate left 4
|
||||
push cx ! push ax ; save crucial registers
|
||||
call pnib ; print hex nibble
|
||||
pop ax ! pop cx ; restore registers
|
||||
dec ch ! jnz lhex ; and loop four times
|
||||
ret
|
||||
pnib: ;print low nibble in AL as hex char
|
||||
and al,0fh ! cmp al,9
|
||||
ja p10 ;above 9 ?
|
||||
add al,'0' ;digit
|
||||
jmp prn
|
||||
p10: add al,'A'-10 ;char a-e
|
||||
prn: mov dl,al
|
||||
|
||||
;******
|
||||
putchar:
|
||||
mov cl,coutf
|
||||
jmp sys_vec
|
||||
|
||||
;******
|
||||
initlbdos:
|
||||
mov cl,seldsk ! mov dx,bootdrv ; select boot disk
|
||||
jmp sys_vec
|
||||
|
||||
;******
|
||||
openfnc:
|
||||
mov cl,openf ! mov dx,offset fcb ; fcb already initialized
|
||||
mov cl,openf
|
||||
jmp sys_vec
|
||||
|
||||
;********
|
||||
;
|
||||
setdma: ;set new dma addr in dx
|
||||
mov cl,dmaf
|
||||
jmp sys_vec
|
||||
|
||||
;********
|
||||
;
|
||||
setdmab: ; set new dma segment base from DX
|
||||
mov cl,dmabf
|
||||
jmp sys_vec
|
||||
|
||||
;******
|
||||
;
|
||||
pcrlf: mov dx,offset crlf ;print carriage return, line feed
|
||||
|
||||
;******
|
||||
;
|
||||
msg: ;print msg starting at dx until $
|
||||
mov cl,pstrf ;print string function
|
||||
jmp sys_vec
|
||||
|
||||
;*****
|
||||
;
|
||||
read:
|
||||
mov dx,offset fcb ! mov cl,readsf
|
||||
; jmp sys_vec
|
||||
|
||||
;******
|
||||
;
|
||||
sys_vec:
|
||||
int bdos_int
|
||||
ret
|
||||
|
||||
;******
|
||||
;
|
||||
stop: hlt ; hard stop 8086 for error
|
||||
jmp stop
|
||||
|
||||
;********************************
|
||||
;*
|
||||
;* DATA AREA
|
||||
;*
|
||||
;********************************
|
||||
|
||||
nofile db cr,lf,'The File CPM.SYS Not Found On This Disk$'
|
||||
rerr db cr,lf,'Error In Reading CPM.SYS$'
|
||||
segment db cr,lf,'Segment Address = $'
|
||||
lenmsg db cr,lf,' Last Offset = $'
|
||||
crlf db cr,lf,'$'
|
||||
|
||||
|
||||
; vector for jmpf indirect to start CP/M
|
||||
|
||||
bios dd abs_zero ; (dummy value)
|
||||
|
||||
org offset bios ; overlay preceding with DW's
|
||||
|
||||
biosstart dw biosoff ; first word is BIOS offset
|
||||
ldseg rw 1 ; second is segment to put CPM.SYS
|
||||
|
||||
|
||||
fcb db 0,'CPM ','SYS',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
|
||||
org (offset $+1) and 0FFFEh ; even address for stack
|
||||
rw 32
|
||||
stack equ offset $
|
||||
|
||||
dseg
|
||||
org stack
|
||||
page1 rb 128
|
||||
|
||||
|
||||
; dummy section for BIOS init label
|
||||
org lbios_offset
|
||||
lbios:
|
||||
|
||||
end
|
||||
|
21
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDCPM.H86
Normal file
21
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDCPM.H86
Normal file
@@ -0,0 +1,21 @@
|
||||
:02000086000078
|
||||
:0400000300000000F9
|
||||
:1B000081E9FD1133C08ED8C706800306048C0E82038CC88ED08ED88EC0BCB8C1
|
||||
:1B001B8101E89200E897003CFF7509BAE100E8A400E9AE008CCAE89400BAB894
|
||||
:1B00368101E88900E89800A1BB012EA355018BD0E87F00BA2601E881002EA1DD
|
||||
:1B0051815501E83600BA0000E8670052E875003C0174153C007409BA0B01E8BA
|
||||
:1B006C816200E96C005A81C28000E9E0FFBA3B01E851005848E80800E846006F
|
||||
:1B0087812EFF2E5301B90404D3C05150E807005859FECD75F3C3240F3C0977B4
|
||||
:1B00A281050430E9020004378AD0B102E92900B10EBA0000E92100B10FBA57F0
|
||||
:1B00BD8101B10FE91700B11AE91200B133E90D00BA5001B109E90500BA570181
|
||||
:1B00D881B114CDE0C3F4E9FCFF0D0A5468652046696C652043504D2E5359537A
|
||||
:1B00F381204E6F7420466F756E64204F6E2054686973204469736B240D0A4544
|
||||
:1B010E8172726F7220496E2052656164696E672043504D2E535953240D0A5324
|
||||
:1B01298165676D656E742041646472657373203D20240D0A202020204C61737C
|
||||
:1301448174204F6666736574203D20240D0A240000000050
|
||||
:02015381002504
|
||||
:1B0157810043504D20202020205359530000000000000000000000000000008D
|
||||
:0601728100000000000006
|
||||
:00000001FF
|
||||
0
|
||||
:1B00
|
288
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/RANDOM.A86
Normal file
288
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/RANDOM.A86
Normal file
@@ -0,0 +1,288 @@
|
||||
;
|
||||
;****************************************************
|
||||
;* *
|
||||
;* Sample Random Access Program for CP/M-86 *
|
||||
;* *
|
||||
;****************************************************
|
||||
;
|
||||
; BDOS Functions
|
||||
;
|
||||
coninp equ 1 ;console input function
|
||||
conout equ 2 ;console output function
|
||||
pstring equ 9 ;print string until '$'
|
||||
rstring equ 10 ;read console buffer
|
||||
version equ 12 ;return version number
|
||||
openf equ 15 ;file open function
|
||||
closef equ 16 ;close function
|
||||
makef equ 22 ;make file function
|
||||
readr equ 33 ;read random
|
||||
writer equ 34 ;write random
|
||||
;
|
||||
; Equates for non graphic characters
|
||||
cr equ 0dh ;carriage return
|
||||
lf equ 0ah ;line feed
|
||||
;
|
||||
;
|
||||
; load SP, ready file for random access
|
||||
;
|
||||
cseg
|
||||
pushf ;push flags in CCP stack
|
||||
pop ax ;save flags in AX
|
||||
cli ;disable interrupts
|
||||
mov bx,ds ;set SS register to base of DATA group
|
||||
mov ss,bx ;set SS, SP with interrupts disabled
|
||||
mov sp,offset stack ; for 80888
|
||||
push ax ;restore the flags
|
||||
popf
|
||||
;
|
||||
; CP/M-86 initial release returns the file
|
||||
; system version number of 2.2: check is
|
||||
; shown below for illustration purposes.
|
||||
;
|
||||
mov cl,version
|
||||
call bdos
|
||||
cmp al,20h ;version 2.0 or later?
|
||||
jnb versok
|
||||
; bad version, message and go back
|
||||
mov dx,offset badver
|
||||
call print
|
||||
jmp abort
|
||||
;
|
||||
versok:
|
||||
; correct version for random access
|
||||
mov cl,openf ;open default fct
|
||||
mov dx,offset fcb
|
||||
call bdos
|
||||
inc al ;err 255 becomes zero
|
||||
jnz ready
|
||||
;
|
||||
; cannot open file, so create it
|
||||
mov cl,makef
|
||||
mov dx,offset fcb
|
||||
call bdos
|
||||
inc al ;err 255 becomes zero
|
||||
jnz ready
|
||||
;
|
||||
; cannot create file, directory full
|
||||
mov dx,offset nospace
|
||||
call print
|
||||
jmp abort ;back to ccp
|
||||
;
|
||||
; loop back to "ready" after each command
|
||||
;
|
||||
ready:
|
||||
; file is ready for processing
|
||||
;
|
||||
call readcom ;read next command
|
||||
mov ranrec,dx ;store input record#
|
||||
mov ranovf,0h ;clear high byte if set
|
||||
cmp al,'Q' ;quit?
|
||||
jnz notq
|
||||
;
|
||||
; quit processing, close file
|
||||
mov cl,closef
|
||||
mov dx,offset fcb
|
||||
call bdos
|
||||
inc al ;err 255 becomes 0
|
||||
jz error ;error message, retry
|
||||
jmps abort ;back to ccp
|
||||
;
|
||||
;
|
||||
; end of quit command, process write
|
||||
;
|
||||
;
|
||||
notq:
|
||||
; not the quit command, random write?
|
||||
cmp al,'W'
|
||||
jnz notw
|
||||
;
|
||||
; this is a random write, fill buffer until cr
|
||||
mov dx,offset datmsg
|
||||
call print ;data prompt
|
||||
mov cx,127 ;up to 127 characters
|
||||
mov bx,offset buff ;destination
|
||||
rloop: ;read next character to buff
|
||||
push cx ;save loop conntrol
|
||||
push bx ;next destination
|
||||
call getchr ;character to AL
|
||||
pop bx ;restore destination
|
||||
pop cx ;restore counter
|
||||
cmp al,cr ;end of line?
|
||||
jz erloop
|
||||
; not end, store character
|
||||
mov byte ptr [bx],al
|
||||
inc bx ;next to fill
|
||||
loop rloop ;decrement cx ..loop if not 0
|
||||
erloop:
|
||||
; end of read loop, store 00
|
||||
mov byte ptr [bx],0h
|
||||
;
|
||||
; write the record to selected record number
|
||||
mov cl,writer
|
||||
mov dx,offset fcb
|
||||
call bdos
|
||||
or al,al ;error code zero?
|
||||
jz ready ;for another record
|
||||
jmps error ;message if not
|
||||
;
|
||||
;
|
||||
;
|
||||
; end of write command, process read
|
||||
;
|
||||
;
|
||||
notw:
|
||||
; not a write command, read record?
|
||||
cmp al,'R'
|
||||
jz ranread
|
||||
jmps error ;skip if not
|
||||
;
|
||||
; read random record
|
||||
ranread:
|
||||
mov cl,readr
|
||||
mov dx,offset fcb
|
||||
call bdos
|
||||
or al,al ;return code 00?
|
||||
jz readok
|
||||
jmps error
|
||||
;
|
||||
; read was successful, write to console
|
||||
readok:
|
||||
call crlf ;new line
|
||||
mov cx,128 ;max 128 characters
|
||||
mov si,offset buff ;next to get
|
||||
wloop:
|
||||
lods al ;next character
|
||||
and al,07fh ;mask parity
|
||||
jnz wloop1
|
||||
jmp ready ;for another command if 00
|
||||
wloop1:
|
||||
push cx ;save counter
|
||||
push si ;save next to get
|
||||
cmp al,' ' ;graphic?
|
||||
jb skipw ;skip output if not graphic
|
||||
call putchr ;output character
|
||||
skipw:
|
||||
pop si
|
||||
pop cx
|
||||
loop wloop ;decrement CX and check for 00
|
||||
jmp ready
|
||||
;
|
||||
;
|
||||
; end of read command, all errors end-up here
|
||||
;
|
||||
;
|
||||
error:
|
||||
mov dx,offset errmsg
|
||||
call print
|
||||
jmp ready
|
||||
;
|
||||
; BDOS entry subroutine
|
||||
bdos:
|
||||
int 224 ;entry to BDOS if by INT 224
|
||||
ret
|
||||
;
|
||||
abort: ;return to CCP
|
||||
Mov Dl, 0
|
||||
mov cl,0
|
||||
call bdos ;use function 0 to end execution
|
||||
;
|
||||
; utility subroutines for console i/o
|
||||
;
|
||||
getchr:
|
||||
;read next console character to a
|
||||
mov cl,coninp
|
||||
call bdos
|
||||
ret
|
||||
;
|
||||
putchr:
|
||||
;write character from a to console
|
||||
mov cl,conout
|
||||
mov dl,al ;character to send
|
||||
call bdos ;send character
|
||||
ret
|
||||
;
|
||||
crlf:
|
||||
;send carriage return line feed
|
||||
mov al,cr ;carriage return
|
||||
call putchr
|
||||
mov al,lf ;line feed
|
||||
call putchr
|
||||
ret
|
||||
;
|
||||
print:
|
||||
;print the buffer addressed by dx until $
|
||||
push dx
|
||||
call crlf
|
||||
pop dx ;new line
|
||||
mov cl,pstring
|
||||
call bdos ;print the string
|
||||
ret
|
||||
;
|
||||
readcom:
|
||||
;read the next command line to the conbuf
|
||||
mov dx,offset prompt
|
||||
call print ;command?
|
||||
mov cl,rstring
|
||||
mov dx,offset conbuf
|
||||
call bdos ;read command line
|
||||
; command line is present, scan it
|
||||
mov ax,0 ;start with 0000
|
||||
mov bx,offset conlin
|
||||
readc: mov dl,[bx] ;next command character
|
||||
inc bx ;to next command position
|
||||
mov dh,0 ;zero high byte for add
|
||||
or dl,dl ;check for end of command
|
||||
jnz getnum
|
||||
ret
|
||||
; not zero, numeric?
|
||||
getnum:
|
||||
sub dl,'0'
|
||||
cmp dl,10 ;carry if numeric
|
||||
jnb endrd
|
||||
mov cl,10
|
||||
mul cl ;multipy accumulator by 10
|
||||
add ax,dx ;+digit
|
||||
jmps readc ;for another char
|
||||
endrd:
|
||||
; end of read, restore value in a and return value in bx
|
||||
mov dx,ax ;return value in DX
|
||||
mov al,-1[bx]
|
||||
cmp al,'a' ;check for lower case
|
||||
jnb transl
|
||||
ret
|
||||
transl: and al,5fH ;translate to upper case
|
||||
ret
|
||||
;
|
||||
;
|
||||
; Template for Page 0 of Data Group
|
||||
; Contains default FCB and DMA buffer
|
||||
;
|
||||
dseg
|
||||
org 05ch
|
||||
fcb rb 33 ;default file control block
|
||||
ranrec rw 1 ;random record position
|
||||
ranovf rb 1 ;high order (overflow) byte
|
||||
buff rb 128 ;default DMA buffer
|
||||
;
|
||||
; string data area for console messages
|
||||
badver db 'sorry, you need cp/m version 2$'
|
||||
nospace db 'no directory space$'
|
||||
datmsg db 'type data: $'
|
||||
errmsg db 'error, try again.$'
|
||||
prompt db 'next command? $'
|
||||
;
|
||||
;
|
||||
; fixed and variable data area
|
||||
;
|
||||
conbuf db conlen ;length of console buffer
|
||||
consiz rs 1 ;resulting size after read
|
||||
conlin rs 32 ;length 32 buffer
|
||||
conlen equ offset $ - offset consiz
|
||||
;
|
||||
rs 31 ;16 level stack
|
||||
stack rb 1
|
||||
db 0 ;end byte for GENCMD
|
||||
end
|
||||
x,ax ;return value in DX
|
||||
mov al,-1[bx]
|
||||
cmp
|
@@ -0,0 +1 @@
|
||||
This folder contains a couple of original DRI CP/M-86 1.1 sources in Assembly language, including the ROM bootstrap and BIOS for the iSBC86/12 with Intel SBC 204 floppy controller.
|
443
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/ROM.A86
Normal file
443
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/ROM.A86
Normal file
@@ -0,0 +1,443 @@
|
||||
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
|
||||
|
@@ -0,0 +1,5 @@
|
||||
disks 2
|
||||
diskdef 0,1,26,6,1024,243,64,64,2
|
||||
diskdef 1,0
|
||||
endef
|
||||
|
65
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/SINGLES.LIB
Normal file
65
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/SINGLES.LIB
Normal file
@@ -0,0 +1,65 @@
|
||||
; 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 31 ;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:
|
||||
;
|
||||
begdat equ offset $ ;Start of Scratch Area
|
||||
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
|
||||
enddat equ offset $ ;End of Scratch Area
|
||||
datsiz equ offset $-begdat ;Size of Scratch Area
|
||||
db 0 ;Marks End of Module
|
||||
|
829
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/TBIOS.A86
Normal file
829
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/TBIOS.A86
Normal file
@@ -0,0 +1,829 @@
|
||||
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
|
||||
|
237
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/TRACK.A86
Normal file
237
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/TRACK.A86
Normal file
@@ -0,0 +1,237 @@
|
||||
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
; * *
|
||||
; * CP/M-86 Accelerator -- Track Buffering Routines *
|
||||
; * *
|
||||
; * This module, when installed in a CBIOS, causes *
|
||||
; * CP/M-86 to perform disk input output on a *
|
||||
; * track by track basis, rather than sector by *
|
||||
; * sector. *
|
||||
; * *
|
||||
; * This speeds diskette access up, often by a *
|
||||
; * factor of four or more times. *
|
||||
; * *
|
||||
; * The actual disk sectors must be a integral *
|
||||
; * multiple of 128 bytes, but do not need to be *
|
||||
; * a power of two multiple unlike the deblocking *
|
||||
; * algorithms supplied with CP/M-86. *
|
||||
; * *
|
||||
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
|
||||
|
||||
; The following three equates must be set to correspond to the
|
||||
; actual disk utilized.
|
||||
|
||||
host_sectsiz equ 1024 ; bytes per actual (physical) disk sector
|
||||
host_spt equ 8 ; actual sectors per track
|
||||
host_fsn equ 1 ; starting sector number (only 0 or 1 allowed)
|
||||
|
||||
|
||||
init:
|
||||
call clear_flags ; Initialize track buffering
|
||||
.
|
||||
.
|
||||
.
|
||||
jmp CCP_entry
|
||||
|
||||
|
||||
seldsk:
|
||||
mov cpm_disk,cl ; save the selected drive
|
||||
test dl,1 ; check logged-in bit
|
||||
jnz old_disk ; not first time selected if nz
|
||||
|
||||
; here if CP/M is about to login to the drive being
|
||||
; selected.
|
||||
|
||||
old_disk:
|
||||
mov bl,cpm_disk ! mov bh,0
|
||||
mov dl,4 ! shl bx,dl ; times 16
|
||||
add bx,offset dpbase ; gives offset from DPBASE
|
||||
ret ; back to BDOS
|
||||
|
||||
setdma:
|
||||
mov dma_offset,cx ; save DMA offset address
|
||||
ret
|
||||
setdma_seg:
|
||||
mov dma_segment,cx ; save DMA segment address
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
read:
|
||||
call 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 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 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
|
||||
return:
|
||||
mov ax,0 ; never return BAD SECTOR code
|
||||
ret
|
||||
|
||||
|
||||
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,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 dl,7 ; log2(128)
|
||||
shl ax,dl ; 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,0 ; start at host sector 0
|
||||
mov cx,host_spt ; for host_spt sectors...
|
||||
next_sect:
|
||||
test sec_flags[BX],1 ; see if this sector has been changed
|
||||
jz not_updated ; no, leave it alone
|
||||
mov sec_flags[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
|
||||
mul bx ; make track buffer offset
|
||||
add ax,offset track_buffer ; make direct pointer
|
||||
mov cur_dma,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.
|
||||
|
||||
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
|
||||
ret
|
||||
|
||||
track_read:
|
||||
; read an entire track from the drive "cur_disk",
|
||||
; the track "cur_track" into "track_buffer".
|
||||
|
||||
ret
|
||||
|
||||
sector_write:
|
||||
; write a physical sector to disk "cur_disk",
|
||||
; track "cur_track", sector "cur_sec" from
|
||||
; the buffer at DS:"cur_dma".
|
||||
|
||||
ret
|
||||
|
||||
|
||||
dseg
|
||||
|
||||
cpm_disk rb 1
|
||||
cpm_track rw 1
|
||||
cpm_sec rw 1
|
||||
|
||||
dma_offset rw 1
|
||||
dma_segment rw 1
|
||||
dma_longword equ dword ptr dma_offset
|
||||
|
||||
cur_disk rb 1
|
||||
cur_sec rw 1
|
||||
cur_track rw 1
|
||||
cur_dma rw 1
|
||||
|
||||
bdos_wr_code rb 1 ; 1 indicates a directory write
|
||||
wr_flag rb 1 ; bit 0 on indicates we have a dirty buffer
|
||||
|
||||
sec_flags rb host_spt ; bit 0 of each byte on indicates
|
||||
; corresponding host sector has been
|
||||
; updated and needs writing.
|
||||
|
||||
track_buffer rb host_sectsiz * host_spt
|
||||
|
Reference in New Issue
Block a user