mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 01:14:21 +00:00
1418 lines
39 KiB
Plaintext
1418 lines
39 KiB
Plaintext
title 'Concurrent CP/M Loader BIOS'
|
||
;*******************************************************
|
||
; Last Modification: 02/16/84
|
||
;
|
||
; L B I O S - 8 6
|
||
; ======================
|
||
;
|
||
; Concurrent CP/M Loader I/O System
|
||
; for
|
||
; CompuPro Computer System
|
||
;
|
||
; Separate Code and Data:
|
||
; -----------------------
|
||
; The code segment is separate from the data
|
||
; segment. The code is ORG'd at 0000h and the
|
||
; data is ORG'd at 0180h relative to the System
|
||
; Data Area.
|
||
;
|
||
; high +---------------------+
|
||
; | Ldr Program Data |
|
||
; + - - - - - - - - - - +
|
||
; | Ldr BIOS Data |
|
||
; +---------------------+ <- 0180h
|
||
; | Ldr BDOS Data |
|
||
; +---------------------+ <- 0000h
|
||
; +---------------------+
|
||
; | Ldr Program Code |
|
||
; + - - - - - - - - - - +
|
||
; | Ldr BIOS Code |
|
||
; +---------------------+ <- 0000h
|
||
; +---------------------+
|
||
; | Ldr BDOS Code |
|
||
; low +---------------------+ <- 0000h
|
||
;
|
||
;*******************************************************
|
||
;
|
||
; The following commands are used to generate CPMLDR.SYS
|
||
; RASM86 LBIOS
|
||
; RASM86 LPROG
|
||
; LINK86 LBIOS3.SYS = LBIOS,LPROG [DATA[ORIGIN[0180]]]
|
||
; GENLDR [nnnn]
|
||
;
|
||
; The following commands are used to generate the
|
||
; boot tracks image BOOTTRKS
|
||
; SID86
|
||
; #RDSKBOOT.SYS ;strips header and
|
||
; #WBOOT,180,37F ;default base page
|
||
; PIP BOOTTRKS = BOOT[O],CPMLDR.SYS[O]
|
||
;
|
||
;*******************************************************
|
||
;
|
||
; Register usage for BIOS interface routines:
|
||
;
|
||
; Entry: AL = function number (in entry)
|
||
; CX = first parameter
|
||
; DX = second parameter
|
||
; DS = ES = system data segment (in entry and init)
|
||
; Exit: AX = return or BIOS error code
|
||
; BX = AX (in exit)
|
||
; DS = ES = preserved through call
|
||
; SS,SP must also be preserved
|
||
; CX,DX,SI,DI,BP can be changed by the BIOS
|
||
;
|
||
;*******************************************************
|
||
;
|
||
; Loader IOS Coding Conventions
|
||
;
|
||
;*******************************************************
|
||
;
|
||
; @ as the first character of a symbol denotes
|
||
; a public variable
|
||
;
|
||
; ? as the first character of a symbol denotes
|
||
; a public label
|
||
;
|
||
; All labels, and code are in lower-case
|
||
; for easier reading.
|
||
;
|
||
; All immediate values (literals) are in uppercase.
|
||
;
|
||
; Fields within data structures have leading
|
||
; letters followed by an underbar and the field
|
||
; name. The data structures defined are:
|
||
;
|
||
; BH_ - BIOS Header
|
||
; DPB_ - Disk Parameter Block
|
||
; DPH_ - Disk Parameter Header
|
||
; IOPB_ - I/O Parameter Block
|
||
;
|
||
; Underscores are used for readiablity otherwise
|
||
; Symbols, code mnemonics, registers are in all upper-case
|
||
; within comments to distinquish them from the code.
|
||
;
|
||
;*******************************************************
|
||
;
|
||
; Character I/O Equates
|
||
;
|
||
;*******************************************************
|
||
|
||
; CompuPro System Support serial definitions
|
||
|
||
SS_BASE equ 050h ;base address
|
||
|
||
SS_MODE equ SS_BASE+0Eh ;CompuPro System Support mode
|
||
SS_COMMAND equ SS_BASE+0Fh ;CompuPro System Support command
|
||
SS_STATUS equ SS_BASE+0Dh ;CompuPro System Support status
|
||
SS_DATA equ SS_BASE+0Ch ;CompuPro System Support data
|
||
|
||
SS_TRANS_READY equ 00000001b ;System Support transmit buffer empty
|
||
SS_RECV_READY equ 00000010b ;System Support data available
|
||
SS_DSR equ 10000000b ;System Support data set ready
|
||
|
||
;*******************************************************
|
||
;
|
||
; Disk Parameter Header Equates
|
||
;
|
||
;*******************************************************
|
||
;
|
||
; +-----+-----+-----+-----+-----+------+-----+-----+
|
||
; 00h | XLT | | DOPEN| |
|
||
; +-----+-----+-----+-----+-----+------+-----+-----+
|
||
; 08h | DPB | CSV | ALV | DIRBCB |
|
||
; +-----+-----+-----+-----+-----+------+-----+-----+
|
||
; 10h | DATBCB | HSHTBL | INIT | LOGIN |
|
||
; +-----+-----+-----+-----+-----+------+-----+-----+
|
||
; 18h | READ | WRITE | UNIT| CHNNL| FCNT|
|
||
; +-----+-----+-----+-----+-----+------+-----+
|
||
|
||
DPH_XLT equ word ptr 0
|
||
DPH_DOPEN equ byte ptr 5
|
||
DPH_DPB equ word ptr 8
|
||
DPH_CSV equ word ptr 10
|
||
DPH_ALV equ word ptr 12
|
||
DPH_DIRBCB equ word ptr 14
|
||
DPH_DATBCB equ word ptr 16
|
||
DPH_HSHTBL equ word ptr 18
|
||
DPH_INIT equ word ptr 20
|
||
DPH_LOGIN equ word ptr 22
|
||
DPH_READ equ word ptr 24
|
||
DPH_WRITE equ word ptr 26
|
||
DPH_UNIT equ byte ptr 28
|
||
DPH_CHNNL equ byte ptr 29
|
||
DPH_FCNT equ byte ptr 30
|
||
|
||
;*******************************************************
|
||
;
|
||
; Disk Parameter Block Equates
|
||
;
|
||
;*******************************************************
|
||
;
|
||
; +-----+-----+-----+-----+-----+-----+-----+-----+
|
||
; 00h | SPT | BSH | BLM | EXM | DSM | DRM..
|
||
; +-----+-----+-----+-----+-----+-----+-----+-----+
|
||
; 08h ..DRM | AL0 | AL1 | CKS | OFF | PSH |
|
||
; +-----+-----+-----+-----+-----+-----+-----+-----+
|
||
; 10h | PHM |
|
||
; +-----+
|
||
|
||
DPB_SPT equ word ptr 0
|
||
DPB_BSH equ byte ptr 2
|
||
DPB_BLM equ byte ptr 3
|
||
DPB_EXM equ byte ptr 4
|
||
DPB_DSM equ word ptr 5
|
||
DPB_DRM equ word ptr 7
|
||
DPB_AL0 equ byte ptr 9
|
||
DPB_AL1 equ byte ptr 10
|
||
DPB_CKS equ word ptr 11
|
||
DPB_OFF equ word ptr 13
|
||
DPB_PSH equ byte ptr 15
|
||
DPB_PHM equ byte ptr 16
|
||
|
||
;*******************************************************
|
||
;
|
||
; Input/Output Parameter Block Definition
|
||
;
|
||
;*******************************************************
|
||
;
|
||
; Read and Write disk parameter equates
|
||
;
|
||
; At the disk read and write entries,
|
||
; all disk I/O parameters are on the stack
|
||
; and the stack at these entries appears as
|
||
; follows:
|
||
;
|
||
; +-------+-------+
|
||
; +14 | DRV | MCNT | Drive and Multi sector count
|
||
; +-------+-------+
|
||
; +12 | TRACK | Track number
|
||
; +-------+-------+
|
||
; +10 | SECTOR | Physical sector number
|
||
; +-------+-------+
|
||
; +8 | DMA_SEG | DMA segment
|
||
; +-------+-------+
|
||
; +6 | DMA_OFF | DMA offset
|
||
; +-------+-------+
|
||
; +4 | RET_SEG | BDOS return segment
|
||
; +-------+-------+
|
||
; +2 | RET_OFF | BDOS return offset
|
||
; +-------+-------+
|
||
; BP+0 | RET_ADR | Local ENTRY return address
|
||
; +-------+-------+ (assumes one level of call
|
||
; from ENTRY routine)
|
||
;
|
||
; These parameters may be indexed and modified
|
||
; directly on the stack and will be removed
|
||
; by the BDOS after the function is complete
|
||
|
||
iopb_mcnt equ byte ptr 15[bp]
|
||
iopb_drive equ byte ptr 14[bp]
|
||
iopb_track equ word ptr 12[bp]
|
||
iopb_sector equ word ptr 10[bp]
|
||
iopb_dmaseg equ word ptr 8[bp]
|
||
iopb_dmaoff equ word ptr 6[bp]
|
||
|
||
;*******************************************************
|
||
;
|
||
; Disk I/O Equates
|
||
;
|
||
;*******************************************************
|
||
|
||
|
||
DPH_FMB equ byte ptr 31 ;floppy mode byte used by driver
|
||
|
||
;*******************************************************
|
||
;
|
||
; Floppy Disk Drivers for Qume Drives
|
||
; and a DISK 1 Controller Board
|
||
;
|
||
;*******************************************************
|
||
|
||
; Floppy mode bits
|
||
|
||
FM_D_DENSITY equ 0000$0001b
|
||
FM_TWO_SIDED equ 0000$0010b
|
||
FM_N_MASK equ 0000$1100b
|
||
|
||
; read/write control string equates for the Intel 8272 FDC
|
||
|
||
D equ byte ptr 1 ;D stands for the drive and head
|
||
; to be used to perform a read/write
|
||
C equ byte ptr 2 ;C stands for the current Cylinder
|
||
; track number 0 - 76 of the medium
|
||
H equ byte ptr 3 ;H stands for head number 0 or 1, as
|
||
; specified in ID field
|
||
R equ byte ptr 4 ;R stands for the Sector number, which
|
||
; will be read or written
|
||
N equ byte ptr 5 ;N stands for the number of data bytes
|
||
; written in a Sector
|
||
EOT equ byte ptr 6 ;EOT stands for the final Sector number
|
||
; of a Cylinder
|
||
GPL equ byte ptr 7 ;GPL stands for the length of Gap 3
|
||
; (spacing between Sectors excluding
|
||
; VCO Sync Field)
|
||
DTL equ byte ptr 8 ;When N is defined as 00, DTL stands
|
||
; for the data length which is going to
|
||
; be read out or write into the sector
|
||
|
||
; Floppy controler port addresses
|
||
|
||
FD_PORT equ 0C0h ;base port address of DISK1 controller
|
||
FDC_S equ FD_PORT ;8272 status register
|
||
FDC_D equ FD_PORT + 1 ;8272 data register
|
||
D1_DMA equ FD_PORT + 2 ;DISK1 dma addr when write
|
||
D1_INTS equ FD_PORT + 2 ;DISK1 interrupt status when read
|
||
|
||
; Main status register bits
|
||
|
||
MSTR_RQM equ 1000$0000b ;master status request
|
||
MSTR_DIO equ 0100$0000b ;master status direction
|
||
MSTR_CB equ 0001$0000b ;command busy status
|
||
|
||
FDC_INT equ 1000$0000b ;FDC interrupt output is asserted
|
||
|
||
RQM_DELAY equ 5 ;12us delay count for master status
|
||
|
||
; Floppy controler function definitions
|
||
|
||
F_SPEC equ 03h ;specify
|
||
F_DSTS equ 04h ;sense drive status
|
||
F_RDAT equ 06h ;read data
|
||
F_RECA equ 07h ;recalibrate
|
||
F_RSTS equ 08h ;sense interrupt status
|
||
F_RDID equ 0Ah ;read id
|
||
F_SEEK equ 0Fh ;seek
|
||
|
||
F_MFM equ 0100$0000b ;double density, MFM mode bit
|
||
|
||
; Floppy retry equate
|
||
|
||
RETRY_COUNT equ 10
|
||
|
||
; Floppy disk status field equates
|
||
|
||
ST0 equ 0 ;status register 0
|
||
ST1 equ 1 ;status register 1
|
||
ST2 equ 2 ;status register 2
|
||
ST_N equ 6 ;result field N
|
||
PCN equ 1 ;present cylinder no. result
|
||
|
||
; Status field bit equates
|
||
|
||
ST0_INTCODE_MSK equ 1100$0000b
|
||
ST0_STRT_NO_END equ 0100$0000b
|
||
ST0_SE equ 0010$0000b ;seek end
|
||
ST0_NR equ 0000$1000b ;not ready
|
||
ST0_UNIT_MASK equ 0000$0011b ;unit mask
|
||
|
||
ST0_RECAL_MASK equ 1111$1100b
|
||
ST0_RECAL_TEST equ 0010$0000b ;seek complete signal
|
||
|
||
ST0_SEEK_MASK equ 1111$1100b
|
||
ST0_VALID_SEEK equ 0010$0000b ;seek complete signal
|
||
|
||
ST1_EOT_END equ 1000$0000b ;end of cylinder
|
||
|
||
ST3_READY equ 0010$0000b ;ready signal
|
||
ST3_TWO_SIDED equ 0000$1000b ;two sided disk
|
||
|
||
ST_N_MASK equ 0000$0011b ;N field mask
|
||
|
||
; Equates for the floppy disk code readability
|
||
|
||
OK equ 00h
|
||
ERROR equ 0FFh
|
||
|
||
HEAD_BIT equ 0000$0100b
|
||
|
||
RW_ERROR equ 01h
|
||
WR_PROT_ERROR equ 02h
|
||
RW_MEDIA_CHANGE equ 0FFh
|
||
|
||
SELDSK_ERROR equ 0
|
||
|
||
CYLINDER_2 equ 2
|
||
|
||
; CCP/M disk control block equates which define the
|
||
; disk types and maximum storage capability of each
|
||
; disk type.
|
||
|
||
; CCP/M to host disk constants
|
||
|
||
CPMSIB equ 1024/128 ;standard sectors in block
|
||
FPYSIB equ 2048/128 ;sectors in floppy disk block
|
||
|
||
S1DSM equ ((77-2)*26)/CPMSIB
|
||
S2DSM equ ((77-2)*2*26)/FPYSIB
|
||
D1DSM equ ((77-2)*2*26)/FPYSIB
|
||
D2DSM equ ((77-2)*2*2*26)/FPYSIB
|
||
D3DSM equ ((77-2)*4*15)/FPYSIB
|
||
D4DSM equ ((77-2)*2*4*15)/FPYSIB
|
||
D5DSM equ ((77-2)*8*8)/FPYSIB
|
||
D6DSM equ ((77-2)*2*8*8)/FPYSIB
|
||
|
||
;*******************************************************
|
||
;
|
||
; 8259A Programmable Interrupt Controller Equates
|
||
;
|
||
;*******************************************************
|
||
;
|
||
; PIC EQUATES: see pages 7-120 -> ... in the 1982 INTEL DATA CATALOG
|
||
;
|
||
; Interupt Structure
|
||
;
|
||
; MASTER PIC: IRQ0 =
|
||
; IRQ1 = DISK 2
|
||
; IRQ2 = interfacer 3 receive ready
|
||
; IRQ3 = interfacer 3 transmit ready
|
||
; IRQ4 = DISK 1
|
||
; IRQ5 =
|
||
; IRQ6 =
|
||
; IRQ7 = Slave input
|
||
;
|
||
; SLAVE PIC: IRQ0 =
|
||
; IRQ1 = Timer 0 ( tick )
|
||
; IRQ2 = Timer 1 ( free )
|
||
; IRQ3 = Timer 2 ( free )
|
||
; IRQ4 = 9511 svrq
|
||
; IRQ5 = 9511 end
|
||
; IRQ6 = SS Tx int
|
||
; IRQ7 = SS Rx int
|
||
|
||
DISABLE_INTS equ 0FFh ;mask to turn off all interrupts
|
||
|
||
NS_EOI equ 20h ;Non specific end of interrupt
|
||
MASTER_PIC_PORT equ 50h
|
||
SLAVE_PIC_PORT equ 52h
|
||
|
||
MASTER_ICW_1 equ 15h ;basic operational mode of chip
|
||
MASTER_ICW_2 equ 40h ;base of chips interrupt vectors
|
||
MASTER_ICW_3 equ 80h ;master/slave map
|
||
MASTER_ICW_4 equ 01h ;interrupt response mode
|
||
|
||
SLAVE_ICW_1 equ MASTER_ICW_1
|
||
SLAVE_ICW_2 equ MASTER_ICW_2 + 8
|
||
SLAVE_ICW_3 equ 07h ;slave I.D. number
|
||
SLAVE_ICW_4 equ MASTER_ICW_4
|
||
|
||
;*******************************************************
|
||
;
|
||
; BIOS Kernel Code Publics and Externals
|
||
;
|
||
;*******************************************************
|
||
CSEG
|
||
|
||
public @sysdat ;force CS over-ride
|
||
public ?conout, ?pmsg
|
||
extrn ?start:near
|
||
|
||
;*******************************************************
|
||
;
|
||
; BIOS Code Header
|
||
;
|
||
;*******************************************************
|
||
org 0000h
|
||
|
||
jmp init ;I/O system initialization
|
||
jmp entry ;I/O system function entry
|
||
jmp ?start ;start of loader program
|
||
|
||
@sysdat rw 1 ;OS Data Segment
|
||
|
||
;*******************************************************
|
||
;
|
||
; BIOS Kernel Data Publics and Externals
|
||
;
|
||
;*******************************************************
|
||
DSEG
|
||
|
||
public @bh_dphtable, @dpha
|
||
|
||
;*******************************************************
|
||
;
|
||
; BIOS Data Header
|
||
;
|
||
;*******************************************************
|
||
org 0000h
|
||
;use the LINK-86 [data[origin[0180]]] option
|
||
;to set the origin of the data segment at 0180h
|
||
|
||
; disk parameter header offset table
|
||
|
||
@bh_dphtable dw offset @dpha ;drive A:
|
||
|
||
;*******************************************************
|
||
;
|
||
; BIOS Code Segment
|
||
;
|
||
;*******************************************************
|
||
CSEG
|
||
|
||
;====
|
||
init:
|
||
;====
|
||
; Entry: DS = ES = system data segment
|
||
; Exit: DS = ES = preserved through call
|
||
|
||
cli ;disable interrupts
|
||
cld ;set forward direction
|
||
|
||
; set up the master PIC
|
||
|
||
mov al,MASTER_ICW_1
|
||
out MASTER_PIC_PORT,al
|
||
mov al,MASTER_ICW_2 ;interupts start at interupt 40h
|
||
out MASTER_PIC_PORT + 1,al
|
||
mov al,MASTER_ICW_3 ;only IRQ 7 has a slave attached
|
||
out MASTER_PIC_PORT + 1,al
|
||
mov al,MASTER_ICW_4 ;Set for 8088 mode
|
||
out MASTER_PIC_PORT + 1,al
|
||
mov al,DISABLE_INTS ;turn off all interupts for now
|
||
out MASTER_PIC_PORT + 1,al
|
||
|
||
; set up the slave PIC
|
||
|
||
mov al, SLAVE_ICW_1
|
||
out SLAVE_PIC_PORT,al
|
||
mov al,SLAVE_ICW_2 ;base of the slave vectors AT 48H
|
||
out SLAVE_PIC_PORT + 1,al
|
||
mov al,SLAVE_ICW_3 ;slave ID number = 7
|
||
out SLAVE_PIC_PORT + 1,al
|
||
mov al,SLAVE_ICW_4 ;8088 mode
|
||
out SLAVE_PIC_PORT + 1,al
|
||
mov al,DISABLE_INTS ;turn off the ints for now
|
||
out SLAVE_PIC_PORT + 1,al
|
||
|
||
sti
|
||
|
||
; initialize the console on the System Support board
|
||
|
||
mov al,0EEh ;AL = mode register 1 ,async 16x rate
|
||
out SS_MODE,al ;send mode register 1
|
||
mov al,07Eh ;AL = mode register 2, internal clock
|
||
out SS_MODE,al ;send mode register 2
|
||
mov al,00$1$0$0$1$1$1b ;trans. on,dtr low,rec. on,no break,
|
||
;...no reset,rts low
|
||
out SS_COMMAND,al ;set up command port
|
||
|
||
; Floppy disk controller initialization.
|
||
; Set up the values for the fdc's three internal timers.
|
||
; HUT (head unload time) = (0fh * 16ms) [240ms]
|
||
; SRT (step rate) = (0fh - 0dh * 1ms increments) [3ms]
|
||
; HLT (head load time) = (31H * 2ms) [98ms]
|
||
; and it sets up the DMA mode
|
||
; ND (non-dma bit) = DMA mode [0]
|
||
;
|
||
; see pages 41 and 38 of the CompuPro DISK 1 manual
|
||
|
||
mov bx,offset specify_cmd ;specify command
|
||
mov cl,length specify_cmd ;sets up initial fdc counter values
|
||
call send_command
|
||
|
||
mov si,offset signon ;signon message defined in INIT module
|
||
call ?pmsg ;print the BIOS signon message
|
||
retf
|
||
|
||
;*******************************************************
|
||
;
|
||
; BIOS Entry Function Dispatch
|
||
;
|
||
;*******************************************************
|
||
|
||
;=====
|
||
entry: ; BIOS Entry Point
|
||
;=====
|
||
; All calls to the BIOS after INIT, enter through this code
|
||
; with a CALLF and must return with a RETF.
|
||
; Entry: AL = function number
|
||
; CX = first parameter
|
||
; DX = second parameter
|
||
; DS = ES = system data segment
|
||
; Exit: AX = BX = return or BIOS error code
|
||
; DS = ES = preserved through call
|
||
; SS,SP must also be preserved
|
||
; CX,DX,SI,DI,BP can be changed by the BIOS
|
||
|
||
cld ;clear direction flag
|
||
xor ah,ah ! shl ax,1 ;index into BIOS function table
|
||
mov bx,ax
|
||
call functab[bx] ;call BIOS kernel routine
|
||
mov bx,ax ;BX = AX
|
||
retf
|
||
|
||
;*******************************************************
|
||
;
|
||
; BIOS Character Output Routines
|
||
;
|
||
;*******************************************************
|
||
|
||
?conout: ;BIOS function 2
|
||
;=======
|
||
; Entry: CL = character
|
||
; Exit: None
|
||
|
||
in al,SS_STATUS ;get uart status
|
||
test al,SS_TRANS_READY ;test if buffer empty
|
||
jz ?conout
|
||
|
||
mov al,cl
|
||
out SS_DATA,al
|
||
ret
|
||
|
||
?pmsg: ;Print String
|
||
;=====
|
||
; Entry: DS:SI = offset of string terminated by 0.
|
||
; Exit: None
|
||
|
||
mov cl,[si] ;get character from buffer
|
||
or cl,cl ! jz pmsg_exit ;check for 0 terminater
|
||
push si
|
||
call ?conout ;output character in CL
|
||
pop si
|
||
inc si
|
||
jmps ?pmsg ;get next character
|
||
pmsg_exit:
|
||
ret
|
||
|
||
;*******************************************************
|
||
;
|
||
; BIOS Disk I/O Routines
|
||
;
|
||
;*******************************************************
|
||
|
||
io_seldsk: ;BIOS function 9
|
||
;=========
|
||
; Entry: CL = disk to be selected
|
||
; DL = (Bit 0): 0 if first select
|
||
; Exit: AX = 0 if illegal select
|
||
; = offset of DPH relative to OS data segment
|
||
|
||
xor bx,bx
|
||
cmp cl,0 ! jne sel_ret ;if not valid drive exit
|
||
mov bx,@bh_dphtable ;get DPH from drive table
|
||
test dl,1 ! jnz sel_ret ;first time select?
|
||
call DPH_LOGIN[bx] ; yes
|
||
sel_ret:
|
||
mov ax,bx
|
||
ret
|
||
|
||
io_read: ;BIOS function 10
|
||
;=======
|
||
; Entry: IOPB filled in (on stack)
|
||
; Exit: AL = 0 if no error
|
||
; = 1 if physical error
|
||
; = 0FFH if media density has changed
|
||
|
||
mov bp,sp ;SS:BP points to IOPB
|
||
cmp iopb_drive,0 ! jne ret_error
|
||
mov bx,@bh_dphtable ;get DPH address
|
||
jmp DPH_READ[bx] ;jump to DPH read routine
|
||
ret_error:
|
||
mov al,1 ;return error if not valid
|
||
ret
|
||
|
||
io_notimp: ;BIOS function not implemented
|
||
;=========
|
||
xor ax,ax ;return success
|
||
ret
|
||
|
||
;*******************************************************
|
||
;
|
||
; Floppy Disk I/O Code Segment
|
||
;
|
||
;*******************************************************
|
||
|
||
fd_login: ;Login routine for the floppy disk drive
|
||
;========
|
||
; This routine figures out
|
||
; 1] what kind of floppy is in the drive
|
||
; 2] does a recal, homes the head
|
||
; 3] saves the floppy mode byte in the DPH.
|
||
; 4] sets up the current floppy mode byte.
|
||
; 5] sets up the dph's
|
||
; 6] returns the addr of the DPH
|
||
; NOTES:
|
||
; there is a DPB for each of the possible disk configurations.
|
||
; 1] SD 128
|
||
; 2] DD 256
|
||
; 3] DD 512
|
||
; 4] DD 1024
|
||
; 5-8] same as 1 - 4 with double sided disks.
|
||
;
|
||
; Entry: BX = DPH offset
|
||
; CL = selected disk
|
||
; Exit: BX = 0 if illegal select
|
||
; = offset of DPH relative to O.S. data segment
|
||
|
||
push bx
|
||
call get_media_type
|
||
pop bx ;BX = DPH offset
|
||
cmp al,ERROR ! jne fd_1
|
||
mov bx,SELDSK_ERROR ;set up the error code for CCP/M
|
||
jmps fd_login_exit
|
||
fd_1:
|
||
mov DPH_FMB[bx],al ;save the current floppy mode byte
|
||
; for this drive in the DPH
|
||
xor ah,ah ;set up the xlat table addr in DPH
|
||
mov di,ax ;save DI for index into DPB table
|
||
shr al,1 ! and al,0FEH
|
||
mov si,ax
|
||
mov ax,xtable[si] ;get the translation table
|
||
mov DPH_XLT[bx],ax ;put the xlat table addr in DPH
|
||
and di,0FFFEh ;get the proper dpb
|
||
mov ax,drv_tbl[di] ;index into the dpb table
|
||
mov DPH_DPB[bx],ax ;and put it in the dph
|
||
fd_login_exit:
|
||
ret ;BX = DPH offset
|
||
|
||
|
||
fd_read: ;Read routine for the floppy disk drive
|
||
;=======
|
||
; BX = DPH offset
|
||
; Exit: AL = 0 if no error
|
||
; = 1 if physical error
|
||
; = 0FFH if media density has changed
|
||
|
||
mov al,DPH_FMB[bx] ;get saved floppy mode
|
||
mov c_fmb,al ;set current floppy mode byte
|
||
mov ax,DPH_XLT[bx] ;get the xlat table
|
||
mov xltbl,ax ;save translation table address
|
||
mov bx,DPH_DPB[bx] ;get the DPB from the DPH
|
||
mov ax,DPB_SPT[bx]
|
||
mov maxsec,ax ;save maximum sector per track
|
||
mov cl,DPB_PSH[bx]
|
||
mov ax,128 ! shl ax,cl ;compute physical record size
|
||
mov secsiz,ax ; and save it
|
||
cmp iopb_mcnt,0 ! jne rw_1
|
||
mov al,1
|
||
ret
|
||
rw_1:
|
||
mov ax,iopb_sector ;is sector < max sector/track
|
||
cmp ax,maxsec ! jb same_trk
|
||
inc iopb_track ; next track
|
||
xor ax,ax
|
||
mov iopb_sector,ax ; initialize sector to 0
|
||
same_trk:
|
||
mov bx,xltbl ;get translation table address
|
||
or bx,bx ! jz no_trans ;if xlt <> 0
|
||
xlat al ; translate sector number
|
||
no_trans:
|
||
mov isector,al ;store sector #
|
||
mov ax,iopb_track ;get track # from IOPB
|
||
mov itrack,ax
|
||
mov ax,iopb_dmaoff ;get dma offset from table
|
||
mov idmaoff,ax
|
||
mov ax,iopb_dmaseg ;get dma segment from IOPB
|
||
mov idmaseg,ax
|
||
call phys_rw ;call read routine
|
||
or al,al ! jnz err_ret ;if error occured return
|
||
mov ax,secsiz ;increment dma offset by the
|
||
add iopb_dmaoff,ax ; physical sector size
|
||
inc iopb_sector ;next sector
|
||
dec iopb_mcnt ;decrement multi sector count
|
||
jnz rw_1 ;if MCNT <> 0 store next sector dma
|
||
|
||
xor ax,ax
|
||
err_ret:
|
||
ret ;return with error code in AL
|
||
|
||
phys_rw: ;these are the physical drivers for the CompuPro
|
||
;-------
|
||
; physical read does the actual read from the floppy.
|
||
;
|
||
; Entry: itrack = the track to read from
|
||
; isector = the sector to read from
|
||
; idmaoff = the dma offset to read to or from
|
||
; idmaseg = the dma segment to read to or from
|
||
;
|
||
; Exit: AL = 0 if no error
|
||
; = 1 if physical error
|
||
; = 2 if Read/Only disk
|
||
; = 0FFH if media density has changed
|
||
|
||
mov rw_retries,RETRY_COUNT
|
||
rw_retry_lp:
|
||
|
||
; setup D, C, H, R, N, EOT, GPL, and DTL fields of RW_CMD
|
||
|
||
mov al,isector ;put sector in the control strings
|
||
inc al ;the bdos expects 0 relative sectors
|
||
mov (rw_cmd + R),al ;record
|
||
mov (rw_cmd + EOT),al ;and the end of track fields
|
||
mov al,F_RDAT ;setup for read command
|
||
test c_fmb,FM_D_DENSITY ;check if double density
|
||
jz rw_not_dd
|
||
or al,F_MFM ;yes - set MFM bit
|
||
rw_not_dd:
|
||
mov rw_cmd,al ;set r/w command in control string
|
||
|
||
mov al,c_fmb
|
||
and al,FM_N_MASK ;get the N value from the mode byte
|
||
shr al,1 ! shr al,1 ; and shift the N bit field to the lsbs
|
||
mov (rw_cmd + N),al ; then stuff the control string
|
||
mov (rw_cmd + DTL),0FFh ;set dtl for all DD operations
|
||
cmp al,0 ! jne zero_dtl ;this checks for a SD floppy
|
||
mov (rw_cmd + DTL),128 ; set for SD operation
|
||
zero_dtl:
|
||
xor ah,ah ;get the gpl as per the
|
||
mov si,ax ! mov al,gpl_tbl[si] ;N value in the FMB
|
||
mov (rw_cmd + GPL),al
|
||
|
||
mov ax,itrack
|
||
test c_fmb,FM_TWO_SIDED
|
||
jz ssided
|
||
shr ax,1 ;two sided drive
|
||
;so seek trk/2 + bit(0)
|
||
ssided:
|
||
; set the cylinder number for the seek and control string
|
||
|
||
mov (seek_cmd + C),al ;set up the seek control
|
||
mov (rw_cmd + C),al ;now the read control
|
||
|
||
; set the drive and head
|
||
|
||
xor al,al ;set the drive
|
||
mov (rw_cmd + H),0
|
||
test c_fmb,FM_TWO_SIDED
|
||
jz side0 ;if double sided
|
||
test itrack,1 ;and track is odd
|
||
jz side0 ;set the head bit
|
||
or al,HEAD_BIT ;set the head bit for the drive field
|
||
mov (rw_cmd + H),1 ;set the head field in the RW_CMD
|
||
side0:
|
||
mov (seek_cmd + D),al ;stuff the seek drive field
|
||
mov (rw_cmd + D),al ; and the RW_CMD drive field
|
||
call seek ;seek to the desired cylinder
|
||
cmp al,ERROR ! je phys_rw_3
|
||
|
||
; set up the floppy controllers dma address
|
||
|
||
mov ax,idmaseg ;get the segment
|
||
mov cl,4 ! rol ax,cl ;(para to bytes) shift add to offset
|
||
mov dx,ax ;save lower 16 bits of paragraph
|
||
and al,0Fh ;get upper nibble of paragraph
|
||
and dx,0FFF0h
|
||
add dx,idmaoff ;add in the offset
|
||
adc al,0 ;add carry into upper nibble
|
||
;send 24 bits to controler
|
||
out D1_DMA,al ;msb
|
||
mov al,dh ! out D1_DMA,al
|
||
mov al,dl ! out D1_DMA,al ;lsb
|
||
|
||
mov bx,offset rw_cmd ;send out the command string
|
||
mov cl,length rw_cmd
|
||
call send_command
|
||
call int_wait ;wait for the read
|
||
mov bx,offset rw_res ;get the results of the read
|
||
mov cl,length rw_res
|
||
call get_results
|
||
;check the interupt code
|
||
mov al,(rw_res + ST0) ;get the interupt code
|
||
and al,ST0_INTCODE_MSK ;check for start but no end
|
||
cmp al,ST0_STRT_NO_END
|
||
jne phys_rw_4 ;due to EOT
|
||
mov al,(rw_res + ST1)
|
||
cmp al,ST1_EOT_END
|
||
jne phys_rw_4
|
||
mov al,OK ;good read so exit
|
||
jmps p_read_exit
|
||
phys_rw_3:
|
||
call recalibrate ;recalibrate on seek errors
|
||
phys_rw_4:
|
||
dec rw_retries
|
||
jz phys_rw_err
|
||
jmp rw_retry_lp
|
||
phys_rw_err:
|
||
mov al,RW_ERROR
|
||
p_read_exit:
|
||
ret
|
||
|
||
get_media_type: ;determine media type for a disk select
|
||
;--------------
|
||
; figures out what kind of disk is in the drive specified
|
||
; Then it builds the Floppy mode byte(C_FMB)
|
||
; It sets the two sided bit, the density bit, and the sector
|
||
; size bits (2, 3) if the disk is DD
|
||
; Exit: AL = current floppy mode byte (C_FMB)
|
||
; AL = ERROR if there was an error
|
||
; C_FMB is set
|
||
|
||
call recalibrate ;recalibrate drive
|
||
cmp al,ERROR ;check for a error in recal
|
||
je media_type_exit ;return on error
|
||
|
||
; Put head 0 over cylinder 2 to sample the disk at the start
|
||
; of the directory. Track 0 is SD on the CompuPro DD disk.
|
||
|
||
mov (seek_cmd + D),0
|
||
mov (seek_cmd + C),CYLINDER_2
|
||
mov fc_retries,RETRY_COUNT ;initialize retry count
|
||
fc_retry_lp:
|
||
call seek ;seek to cylinder 2
|
||
cmp al,ERROR ! jne cylinder_2_now
|
||
dec fc_retries ! jnz fc_retry_lp
|
||
|
||
jmps media_type_exit ;return with error
|
||
cylinder_2_now:
|
||
mov c_fmb,0 ;set current floppy mode byte to 0
|
||
|
||
; get the number of sides from the FDD's status byte
|
||
|
||
test sdst_res,ST3_TWO_SIDED
|
||
jz single_sided
|
||
or c_fmb,FM_TWO_SIDED ;set two sided field
|
||
single_sided:
|
||
; resolve the density either SD or DD we should be over cylinder 2
|
||
; if the read id for a DD disk fails try a SD disk
|
||
|
||
mov rd_id_cmd,F_RDID + F_MFM ;set read id for DD
|
||
call read_id
|
||
jz sec_size
|
||
mov rd_id_cmd,F_RDID ;set read id for SD
|
||
call read_id
|
||
jz f_sel_com
|
||
dec fc_retries ! jnz single_sided
|
||
|
||
mov al,ERROR
|
||
jmps media_type_exit
|
||
sec_size:
|
||
; first set the d_density bit in the c_fmb
|
||
; get the sector size from the N field returned by the FDC
|
||
|
||
or c_fmb,FM_D_DENSITY ;or in the DD bit in the FMB
|
||
mov al,(rd_id_res + ST_N) ;get the N field
|
||
and al,ST_N_MASK ;mask for validity
|
||
shl al,1 ! shl al,1 ;setup mask for C_FMB
|
||
or c_fmb,al ;or the mask into the current mode byte
|
||
f_sel_com:
|
||
mov al,c_fmb
|
||
media_type_exit:
|
||
ret
|
||
|
||
sense_drv_stat: ;sense drive status
|
||
;--------------
|
||
; Exit: AL = OK if drive is ready
|
||
; AL = ERROR if the drive is not ready
|
||
|
||
mov bx,offset sdst_cmd
|
||
mov D[bx],0 ;set the drive, head = 0
|
||
mov cl,length sdst_cmd
|
||
call send_command ;Sense drive status command
|
||
mov bx,offset sdst_res
|
||
mov cl,length sdst_res
|
||
call get_results
|
||
|
||
; Note:
|
||
; the status byte returned by this call has the fdd's
|
||
; ready line status bit in it (bit(3))
|
||
; if the upper nibble = 2 the door is closed.
|
||
; else if the upper nibble = 4 the is open.
|
||
|
||
xor al,al
|
||
test sdst_res,ST3_READY ;make sure the drive is ready
|
||
jnz sds_exit
|
||
mov al,ERROR
|
||
sds_exit:
|
||
ret
|
||
|
||
recalibrate: ;recalibrate drive
|
||
;-----------
|
||
; Exit: AL = OK if everthing went OK
|
||
; AL = ERROR if it could not find the track 0
|
||
; or the drive was off line
|
||
|
||
call sense_drv_stat ;Sense drive status
|
||
cmp al,ERROR ! je recal_exit
|
||
mov bx,offset recal_cmd
|
||
mov D[bx],0 ;stuff the control string
|
||
mov cl,length recal_cmd
|
||
call send_command ;send the recal command
|
||
call int_wait ;wait for the recal to happen
|
||
mov al,(sist_res + ST0)
|
||
and al,ST0_RECAL_MASK ;get status register 0
|
||
cmp al,ST0_RECAL_TEST ; and make sure recal was ok
|
||
mov al,OK
|
||
je recal_exit
|
||
mov al,ERROR
|
||
recal_exit:
|
||
ret
|
||
|
||
seek: ;seek sends the seek command to the fdc
|
||
;----
|
||
; Entry: SEEK_CMD must be set up on the way in
|
||
;
|
||
; Exit: AL = OK if everthing went OK
|
||
; AL = ERROR if it could not find the right track
|
||
; or the drive was off line
|
||
|
||
call sense_drv_stat ;sense drive status
|
||
cmp al,ERROR ! je sk_exit
|
||
mov bx,offset seek_cmd ;send the seek command
|
||
mov cl,length seek_cmd
|
||
call send_command
|
||
call int_wait ;wait for the seek
|
||
mov al,(sist_res + ST0) ;get status register 0
|
||
and al,ST0_SEEK_MASK ; and make sure its ok
|
||
cmp al,ST0_VALID_SEEK ! jne sk_err_exit
|
||
mov al,(seek_cmd + C) ;compare the cylinder we're over
|
||
cmp al,(sist_res + PCN) ;to the one we wanted
|
||
mov al,OK
|
||
je sk_exit
|
||
sk_err_exit:
|
||
mov al,ERROR
|
||
sk_exit:
|
||
ret
|
||
|
||
read_id:
|
||
;-------
|
||
; read ID expects the control byte set up before it is called.
|
||
; Entry: RD_ID_CMD (read ID control string set up)
|
||
; Exit: Z flag set if it could read an ID
|
||
; Z flag reset if the drive was not ready
|
||
|
||
mov bx,offset rd_id_cmd
|
||
mov D[bx],0 ;set the drive, head = 0
|
||
mov cl,length rd_id_cmd
|
||
call send_command ;send the read id command
|
||
call int_wait ;wait for the read
|
||
mov bx,offset rd_id_res ;get the results
|
||
mov cl,length rd_id_res
|
||
call get_results
|
||
mov al,rd_id_res + ST0 ;get the results
|
||
and al,ST0_INTCODE_MSK ;mask for the interupt code
|
||
cmp al,OK ;set Z flag if no error
|
||
ret
|
||
|
||
send_command: ;send command to 8272
|
||
;------------
|
||
; Entry: BX = address of the command string
|
||
; CL = the length of the command string
|
||
|
||
in al,FDC_S
|
||
test al,MSTR_CB ! jnz send_command
|
||
|
||
xor ch,ch
|
||
cli
|
||
snd_cmd1:
|
||
mov al,RQM_DELAY ;must delay 12us before polling
|
||
snd_cmd2: ;FDC status to insure valid results
|
||
dec al ! jnz snd_cmd2
|
||
snd_cmd3:
|
||
in al,FDC_S ;get master status from 8272
|
||
test al,MSTR_RQM ! jz snd_cmd3
|
||
test al,MSTR_DIO ! jnz snd_cmd3
|
||
|
||
mov al,[bx] ! out FDC_D,al ;send command string to 8272
|
||
inc bx
|
||
loop snd_cmd1 ;next byte of command string
|
||
|
||
sti
|
||
ret
|
||
|
||
get_results: ;get results form 8272
|
||
;-----------
|
||
; Entry: CL = number of bytes to expect from the fdc
|
||
; BX = addr of where to put the results
|
||
; Exit: the location starting where BX was pointing
|
||
; for a length of CX will have the results from the
|
||
; fdc result phase
|
||
|
||
in al,FDC_S
|
||
test al,MSTR_CB ! jz get_results
|
||
|
||
xor ch,ch
|
||
get_res1:
|
||
mov al,RQM_DELAY ;must delay 12us before polling
|
||
get_res2: ;FDC status to insure valid results
|
||
dec al ! jnz get_res2
|
||
get_res3:
|
||
in al,FDC_S ;get master status from 8272
|
||
test al,MSTR_RQM ! jz get_res3
|
||
test al,MSTR_DIO ! jz get_res3
|
||
|
||
in al,FDC_D ;get the result status
|
||
mov [bx],al ! inc bx
|
||
loop get_res1
|
||
|
||
ret
|
||
|
||
int_wait: ;interupt wait
|
||
;--------
|
||
; this routine does a flag wait on the fdc operation.
|
||
|
||
push bp
|
||
|
||
int_w1:
|
||
in al,D1_INTS ;wait for FDC interrupt to be asserted
|
||
test al,FDC_INT ! jz int_w1
|
||
|
||
; check the direction of data xfer from the FDC's main status port
|
||
|
||
flint_lp:
|
||
in al,FDC_S ;wait for the fdc to become ready
|
||
test al,MSTR_RQM ! jz flint_lp ; for data xfer
|
||
|
||
test al,MSTR_DIO ;if the fdc want to send us data,
|
||
jnz fdc_to_processor ; it must be our expected status
|
||
;the fdc is expecting a command,
|
||
; so query the interrupt status
|
||
; Note:
|
||
; neither the recalibrate or the seek commands have
|
||
; a result phase. Therefore it is mandatory to issue the
|
||
; rdcsist command to properly terminate these commands.
|
||
; See the 8272 spec sheet for the details.
|
||
|
||
fdcsist:
|
||
in al,FDC_S
|
||
test al,MSTR_CB ! jnz fdcsist
|
||
|
||
fdcsist1:
|
||
in al,FDC_S ;poll the fdc to be ready for data com
|
||
test al,MSTR_RQM ! jz fdcsist1
|
||
test al,MSTR_DIO ! jnz fdcsist1
|
||
|
||
mov al,F_RSTS ! out FDC_D,al ;send sense interrupt status command
|
||
mov bx,offset sist_res
|
||
mov cl,length sist_res ;get the two byte result from the
|
||
call get_results ;fdc
|
||
fdc_to_processor:
|
||
pop bp
|
||
ret
|
||
|
||
;*******************************************************
|
||
;
|
||
; BIOS Data Segment
|
||
;
|
||
;*******************************************************
|
||
DSEG
|
||
|
||
; BIOS Function Table
|
||
|
||
functab dw io_notimp ; 0 - console status
|
||
dw io_notimp ; 1 - console input
|
||
dw io_notimp ; 2 - console output
|
||
dw io_notimp ; 3 - list output status
|
||
dw io_notimp ; 4 - list output
|
||
dw io_notimp ; 5 - aux input
|
||
dw io_notimp ; 6 - aux output
|
||
dw io_notimp ; 7 - CCP/M function
|
||
dw io_notimp ; 8 - CCP/M function
|
||
dw io_seldsk ; 9 - select disk
|
||
dw io_read ;10 - read sector
|
||
dw io_notimp ;11 - write sector
|
||
dw io_notimp ;12 - flush buffers
|
||
dw io_notimp ;13 - CCP/M function
|
||
dw io_notimp ;14 - char. device init
|
||
dw io_notimp ;15 - console output status
|
||
dw io_notimp ;16 - aux input status
|
||
dw io_notimp ;17 - aux output status
|
||
|
||
signon db 13,10
|
||
db 'Concurrent CP/M CompuPro Loader IOS',13,10,0
|
||
|
||
;*******************************************************
|
||
;
|
||
; Floppy Disk I/O Data Segment
|
||
;
|
||
;*******************************************************
|
||
|
||
imcnt db 0
|
||
itrack dw 0
|
||
isector db 0
|
||
idmaoff dw 0
|
||
idmaseg dw 0
|
||
|
||
; sides density bytes/sec
|
||
drv_tbl dw dpbs1 ;ss,sd, 128
|
||
dw dpbs2 ;ds,sd, 128
|
||
dw dpbd1 ;ss,dd, 256
|
||
dw dpbd2 ;ds,dd, 256
|
||
dw dpbd3 ;ss,dd, 512
|
||
dw dpbd4 ;ds,dd, 512
|
||
dw dpbd5 ;ss,dd, 1024
|
||
dw dpbd6 ;ds,dd, 1024
|
||
|
||
; GAP 3 Length, these values indicate spacing between
|
||
; sectors excluding VCO and Sync Field
|
||
|
||
gpl_tbl db 7 ;SD 128 byte sectors
|
||
db 1ah ;DD 256 byte sectors
|
||
db 0fh ;DD 512 byte sectors
|
||
db 08 ;DD 1024 byte sectors
|
||
|
||
; FLOPPY MODE BYTE AND TABLE
|
||
; B B B B B B B B
|
||
; 7 6 5 4 3 2 1 0
|
||
; \ / | + ------- set = double density, reset = single density
|
||
; | +---------- set = two sided, reset = single sided
|
||
; +------------- 0 = 128 byte sectors
|
||
; 1 = 256 byte sectors
|
||
; 2 = 512 byte sectors
|
||
; 3 = 1024 byte sectors
|
||
|
||
c_fmb db 0 ;the current floppy mode byte
|
||
|
||
;*******************************************************
|
||
;
|
||
; Intel 8272 FDC Command Set Data Strctures
|
||
;
|
||
;*******************************************************
|
||
|
||
; READ/WRITE DATA Command String
|
||
; D C H R N EOT GPL DTL
|
||
rw_cmd db 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||
|
||
; r/w result string
|
||
; S S S
|
||
; T T T
|
||
; 0 1 2 C H R N
|
||
rw_res db 0, 0, 0, 0, 0, 0, 0
|
||
|
||
; READ ID Command String
|
||
;
|
||
rd_id_cmd db 0, 0
|
||
; | +--- head and drive
|
||
; +------ control byte
|
||
; S S S ;read ID result string
|
||
; T T T
|
||
; 0 1 2 C H R N
|
||
rd_id_res db 0, 0, 0, 0, 0, 0, 0
|
||
|
||
; RECALIBRATE Command and Result String
|
||
;
|
||
recal_cmd db F_RECA, 0 ;re-cal command string
|
||
|
||
; SENSE INTERRUPT STATUS Result String
|
||
;
|
||
sist_res db 0, 0 ; returned status from an interrupt
|
||
; | +--- present cylinder number
|
||
; +------ fdc status byte 0
|
||
|
||
; SPECIFY Command String
|
||
;SRT = 3ms, HUT = 240ms
|
||
;HLT = 112ms, DMA = on
|
||
specify_cmd db F_SPEC, 1101$1111b, 0111000$0b
|
||
|
||
; SENSE DRIVE STATUS Command/Result Strings
|
||
;
|
||
sdst_cmd db F_DSTS, 0 ;sense drive status control string
|
||
sdst_res db 0 ;sense drive status result byte ST3
|
||
|
||
; SEEK Command String
|
||
;
|
||
seek_cmd db F_SEEK, 0, 0
|
||
; | +--- new cylinder number
|
||
; +------ head and drive
|
||
|
||
; Retry counter variables
|
||
|
||
rw_retries db 0
|
||
fc_retries db 0 ;first call retries for first recal
|
||
|
||
;*******************************************************
|
||
;
|
||
; these are the disk parameters used by the disk routines
|
||
;
|
||
;*******************************************************
|
||
|
||
xltbl dw 0 ;translation table address
|
||
maxsec dw 0 ;max sectors per track
|
||
secsiz dw 0 ;sector size
|
||
|
||
; floppy disk 0
|
||
@dpha dw xltd3
|
||
db 0, 0, 0 ;scratch area
|
||
db 0 ;door open flag
|
||
db 0, 0 ;scratch area
|
||
dw dpbd6 ;disk paramater table
|
||
dw 0FFFFH, 0FFFFH ;checksum, allocation vector
|
||
dw 0FFFFH ;directory bcb
|
||
dw 0FFFFH ;data bcb
|
||
dw 0FFFFH ;hash table
|
||
|
||
dw 0 ;init routine
|
||
dw fd_login ;login routine
|
||
dw fd_read ;read routine
|
||
dw 0 ;write routine
|
||
db 0 ;unit
|
||
db 0 ;channel 0
|
||
db 1 ;one flag used
|
||
|
||
db 0 ;floppy mode byte used by driver
|
||
|
||
; 1944: 128 Byte Record Capacity
|
||
; 243: Kilobyte Drive Capacity
|
||
; 64: 32 Byte Directory Entries
|
||
; 64: Checked Directory Entries
|
||
; 128: 128 Byte Records / Directory Entry
|
||
; 8: 128 Byte Records / Block
|
||
; 8: 128 Byte Records / Track
|
||
; 2: Reserved Tracks
|
||
|
||
dpbs1: ;single density, single sided.
|
||
DW 26 ;sectors per track
|
||
DB 3, 7, 0 ;block size=1k, exm=0
|
||
DW S1DSM-1, 64-1 ;dsm, drm
|
||
DB 0C0h,000h ;2 blocks for directory
|
||
DW 8010h ;64/4 cks
|
||
DW 2 ;offset by 2 tracks
|
||
db 0 ;physical sector shift
|
||
db 0 ;physical sector mask
|
||
|
||
; 3888: 128 Byte Record Capacity
|
||
; 486: Kilobyte Drive Capacity
|
||
; 128: 32 Byte Directory Entries
|
||
; 128: Checked Directory Entries
|
||
; 256: 128 Byte Records / Directory Entry
|
||
; 16: 128 Byte Records / Block
|
||
; 26: 128 Byte Records / Track
|
||
; 4: Reserved Tracks
|
||
|
||
dpbs2: ;single density, double sided.
|
||
DW 26 ;sectors per track
|
||
DB 4, 15, 1 ;block size=2k, exm=1
|
||
DW S2DSM-1, 128-1 ;dsm, drm
|
||
DB 0C0h,000h ;2 blocks for directory
|
||
DW 8020h ;128/4 cks
|
||
DW 2*2 ;offset by 4 tracks
|
||
db 0 ;physical sector shift
|
||
db 0 ;physical sector mask
|
||
|
||
; 3888: 128 Byte Record Capacity
|
||
; 486: Kilobyte Drive Capacity
|
||
; 128: 32 Byte Directory Entries
|
||
; 128: Checked Directory Entries
|
||
; 128: 128 Byte Records / Directory Entry
|
||
; 16: 128 Byte Records / Block
|
||
; 52: 128 Byte Records / Track
|
||
; 2: Reserved Tracks
|
||
|
||
dpbd1: ;double density, single sided. (256 byte sectors)
|
||
DW 26 ;physical sectors per track
|
||
DB 4, 15, 0 ;block size = 2k, exm=0 (should be 1)
|
||
DW D1DSM-1, 128-1 ;dsm, drm
|
||
DB 0C0h,000h ;2 blocks for directory
|
||
DW 8020h ;128/4 cks
|
||
DW 2 ;offset 2 tracks
|
||
db 1 ;physical sector shift
|
||
db 1 ;physical sector mask
|
||
|
||
; 7792: 128 Byte Record Capacity
|
||
; 974: Kilobyte Drive Capacity
|
||
; 256: 32 Byte Directory Entries
|
||
; 256: Checked Directory Entries
|
||
; 128: 128 Byte Records / Directory Entry
|
||
; 16: 128 Byte Records / Block
|
||
; 52: 128 Byte Records / Track
|
||
; 4: Reserved Tracks
|
||
|
||
dpbd2: ;double density, double sided. (256 byte sectors)
|
||
DW 26 ;physical sectors per track
|
||
DB 4, 15, 0 ;2k block size, exm=0
|
||
DW D2DSM-1, 256-1 ;dsm, drm
|
||
DB 0F0h,000h ;4 directory blocks
|
||
DW 8040h ;256/4 cks
|
||
DW 2*2 ;offset 4 tracks
|
||
db 1 ;physical sector shift
|
||
db 1 ;physical sector mask
|
||
|
||
; 4496: 128 Byte Record Capacity
|
||
; 562: Kilobyte Drive Capacity
|
||
; 128: 32 Byte Directory Entries
|
||
; 128: Checked Directory Entries
|
||
; 128: 128 Byte Records / Directory Entry
|
||
; 16: 128 Byte Records / Block
|
||
; 60: 128 Byte Records / Track
|
||
; 2: Reserved Tracks
|
||
|
||
dpbd3: ;double density, single sided. (512 byte sectors)
|
||
DW 15 ;physical sectors per track
|
||
DB 4, 15, 0 ;2k block size, exm=0
|
||
DW D3DSM-1, 128-1 ;dsm, drm
|
||
DB 0C0h,000h ;2 directory blocks
|
||
DW 8020h ;128/4 cks
|
||
DW 2 ;offset 2 tracks
|
||
db 2 ;physical sector shift
|
||
db 3 ;physical sector mask
|
||
|
||
; 8992: Byte Record Capacity
|
||
; 1124: Kilobyte Drive Capacity
|
||
; 256: 32 Byte Directory Entries
|
||
; 256: Checked Directory Entries
|
||
; 128: 128 Byte Records / Directory Entry
|
||
; 16: 128 Byte Records / Block
|
||
; 60: 128 Byte Records / Track
|
||
; 4: Reserved Tracks
|
||
|
||
dpbd4: ;double density, double sided. (512-byte sectors)
|
||
DW 15 ;physical sectors per track
|
||
DB 4, 15, 0 ;2k block size, exm=0
|
||
DW D4DSM-1, 256-1 ;dsm, drm
|
||
DB 0F0h,000h ;4 directory blocks
|
||
DW 8040h ;256/4 cks
|
||
DW 2*2 ;offset 4 tracks
|
||
db 2 ;physical sector shift
|
||
db 3 ;physical sector mask
|
||
|
||
; 4800: 128 Byte Record Capacity
|
||
; 600: Kilobyte Drive Capacity
|
||
; 128: 32 Byte Directory Entries
|
||
; 128: Checked Directory Entries
|
||
; 128: 128 Byte Records / Directory Entry
|
||
; 16: 128 Byte Records / Block
|
||
; 8: 128 Byte Records / Track
|
||
; 2: Reserved Tracks
|
||
|
||
dpbd5: ;double density, single sided. (1024-byte sectors)
|
||
DW 8 ;physical sectors per track
|
||
DB 4, 15, 0 ;2k block size, exm=0
|
||
DW D5DSM-1, 128-1 ;dsm, drm
|
||
DB 0C0h,000h ;2 directory blocks
|
||
DW 8020h ;128/4 cks, semi-permanent
|
||
DW 2 ;offset 2 tracks
|
||
db 3 ;physical sector shift
|
||
db 7 ;physical sector mask
|
||
|
||
; 9600: 128 Byte Record Capacity
|
||
; 1200: Kilobyte Drive Capacity
|
||
; 256: 32 Byte Directory Entries
|
||
; 256: Checked Directory Entries
|
||
; 128: 128 Byte Records / Directory Entry
|
||
; 16: 128 Byte Records / Block
|
||
; 8: 128 Byte Records / Track
|
||
; 4: Reserved Tracks
|
||
|
||
dpbd6: ;double density, double sided. (1024-byte sectors)
|
||
DW 8 ;physical sectors per track
|
||
DB 4, 15, 0 ;2k block size, exm=0
|
||
DW D6DSM-1, 256-1 ;dsm, drm
|
||
DB 0F0h,000h ;4 directory blocks
|
||
DW 8040h ;256/4 cks, semi-permanent
|
||
DW 2*2 ;offset 4 tracks
|
||
db 3 ;physical sector shift
|
||
db 7 ;physical sector mask
|
||
|
||
; THESE ARE THE SKEW TABLES
|
||
; sector translation tables (for floppy disks)
|
||
|
||
xtable dw xlts ;single 128
|
||
dw xltd1 ;double 256
|
||
dw xltd2 ;double 512
|
||
dw xltd3 ;double 1024
|
||
|
||
xlts db 0,6,12,18,24,4,10,16,22,2,8,14,20 ;physical skew = 6
|
||
db 1,7,13,19,25,5,11,17,23,3,9,15,21 ;26 sectors/track
|
||
;128 byte sectors
|
||
xltd1 db 0,9,18,1,10,19,2,11,20,3,12,21 ;physical skew = 9
|
||
db 4,13,22,5,14,23,6,15,24,7,16,25 ;26 sectors/track
|
||
db 8,17 ;256 byte sectors
|
||
|
||
xltd2 db 0,4,8,12,1,5,9,13 ;physical skew = 4
|
||
db 2,6,10,14,3,7,11 ;15 sectors/track
|
||
;512 byte sectors
|
||
xltd3 DB 0,3,6,1,4,7,2,5 ;physical skew = 3
|
||
;8 sectors per track
|
||
;1024 byte sectors
|
||
|
||
END
|
||
|