Files
open-simh.simtools/extracters/rstsflx/dosrxio.c
Paul Koning bf7c17ab4a Add RSTSFLX V2.6. This is a file system access utility for RSTS
file systems.  It supports reading and writing as well as a number
of other operations, such as octal dump, file system initialize,
and file system check ("clean").

This was originally maintained as a Subversion repository at
svn://akdesign.dyndns.org/flx/branches/V2.6.
as suggested by Timothe Litt on the SIMH mailing list.
2016-04-27 15:00:42 -04:00

204 lines
5.3 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* floppy disk I/O for DOS
*
* based on RXRTDVRA.ASM by Robert Morse and John Dudeck
*/
/* ---------------------------------------------------------------
* IBM ROM BIOS Definitions
* ---------------------------------------------------------------
*/
#define DKOP_RUPT 013h /* interrupt to call ROM BIOS */
#define DKOP_RESET 000h /* reset controller */
#define DKOP_STATUS 001h /* read status from last operation */
#define DKOP_READ 002h /* read sectors */
#define DKOP_WRITE 003h /* write sectors */
#define DKOP_VERIFY 004h /* verify sectors */
#define DKOP_CHANGE 016h /* test changed status */
#define DKOP_SETTYPE 017h /* set media type in drive */
#define DKST_TIMEOUT 080h /* drive not ready */
#define DKST_BADSEEK 040h /* seek failed */
#define DKST_BADNEC 020h /* NEC controller failed */
#define DKST_BADCRC 010h /* read CRC error */
#define DKST_BADDMA 009h /* attempt to DMA over 64K boundary */
#define DKST_OVERRUN 008h /* DMA overrun */
#define DKST_CHANGED 006h /* media changed */
#define DKST_RNF 004h /* sector not found */
#define DKST_WRPROT 003h /* write-protected diskette */
#define DKST_ADRMARK 002h /* address mark not found */
#define DKST_BADCMD 001h /* invalid command */
#define BIOS_DATA_SEG 0040h
/* #define BIOSDATA segment at BIOS_DATA_SEG /* BIOS data segment-- */
#define bios_dsk_state (*(byte *)(0x0090)) /* drive 0 media state */
#define BIOS_DSK_360K 074h /* 360kb media established */
#define BIOS_DSK_RX50 054h /* RX50 media established in drive */
/* (same as 360kb except single steps */
/* for 96 tpi media) */
/* Convert block number to cylinder, head, sector for RT11-RX50.
* This is different for RT11 than for Rainbow DOS:
* For DOS, for cylinders 2 through 79, the sectors are interleaved 2:1.
* (DOS capability is not supported in this RT11 version).
* For RT11, all sectors are interleaved 2:1, and each subsequent
* track has the first logical block offset by 2 more sectors.
*/
void makechs_rx50 (int block, int *trk, int *sec)
{
int t, s;
t = block / 10;
s = block % 10 + 1;
if (s < 6) s = (s - 1) * 2 + 1;
else s = (s - 5) * 2;
s += t * 2;
while (s > 10) s -= 10;
t++;
*trk = t;
*sec = s;
}
;Common routine for read, write and verify.
;
;Given: AL = operation code
; ES:DI = pointer to IOP, which contains
; iop_block = starting block number
; iop_bufptr = starting buffer address
; iop_count = number of blocks
;Returns: AX = IOP error code
; xx_count = number of requested blocks NOT transferred
do_readwrite:
mov es:iop_rwvoloff[di], offset vol_name
mov es:iop_rwvolseg[di], cs
mov xx_oper, al ;save operation code
mov ax, es:iop_block[di] ;set starting block number
test ax, ax ;JRD check for negative
jge do_rw1 ;JRD
xor ax, ax ;JRD
do_rw1:
push si ;JRD
mov si, bpb_pointer ;JRD
cmp ax, bpb_totsects[si] ;JRD test for too big
jle do_rw2 ;JRD
mov ax, bpb_totsects[si] ;JRD limit to maximum
do_rw2:
pop si ;JRD
mov xx_block, ax
mov ax, es:iop_count[di] ;set block count
mov xx_count, ax
test ax, ax
jz dorw_success ; quit if 0 sectors to do
mov ax, es:iop_bufoff[di] ;set starting buffer offset
mov xx_offset, ax ; and segment
mov ax, es:iop_bufseg[di]
mov xx_seg, ax
dorw_loop:
mov xx_retries, 5 ;set retry counter
dorw_again:
mov ax, BIOS_DATA_SEG ;set diskette status to single
mov es, ax ; stepping for 96 tpi
mov es:bios_dsk_state, BIOS_DSK_RX50
mov ax, xx_block ;load block number
call makechs_rx50 ; and convert to CHS
mov dl, PHYS_DRIVE_0 ;set drive number
mov ah, xx_oper ;operation code
mov al, 1 ;transfer 1 sector
les bx, xx_buf ;set ES:BX to buffer address
int DKOP_RUPT ;invoke ROM BIOS to do it
mov xx_status, ah ; and save returned status
test ah, ah ;test for error
jnz dorw_error ; break loop on error
inc xx_block ;advance to next block
add xx_offset, PHYS_BLKSIZE ;advance buffer pointer
dec xx_count ;count blocks
jnz dorw_loop ; and continue until done
dorw_success:
xor ax, ax ;set no-error code
ret
;Analyze read/write errors and either make another attempt or
;set the error code and return.
dorw_error:
mov al, IOPST_NOTRDY
test ah, DKST_TIMEOUT
jnz dorw_giveup
mov al, IOPST_SEEK
test ah, DKST_BADSEEK
jnz dorw_retry
mov al, IOPST_IOERR
test ah, DKST_BADNEC
jnz dorw_retry
cmp ah, DKST_OVERRUN
je dorw_retry
mov al, IOPST_CRC
cmp ah, DKST_BADCRC
je dorw_retry
mov al, IOPST_BADCMD
cmp ah, DKST_BADDMA
je dorw_giveup
cmp ah, DKST_BADCMD
je dorw_giveup
mov al, IOPST_BADCHNG
cmp ah, DKST_CHANGED
jne dorw_nochange
cmp open_count, 0
jg dorw_giveup ;error if change with any files open
jmp short dorw_reset ; else do it again
dorw_nochange:
mov al, IOPST_RNF
cmp ah, DKST_RNF
je dorw_retry
mov al, IOPST_WRPROT
cmp ah, DKST_WRPROT
je dorw_giveup
mov al, IOPST_UNKMEDIA
cmp ah, DKST_ADRMARK
je dorw_retry
mov al, IOPST_IOERR
jmp short dorw_giveup
dorw_retry:
dec xx_retries ;count retries
jle dorw_giveup
dorw_reset:
mov ah, DKOP_RESET ;reset the disk controller
int DKOP_RUPT
jmp dorw_again ; and try again
dorw_giveup:
mov ah, high IOPST_ERR ;complete the driver error return code
ret
int rxread (int block, int size, void *buffer)
{
return (rxio (DKOP_READ, block, size, buffer));
}
int rxwrite (int block, int size, void *buffer)
{
return (rxio (DKOP_WRITE, block, size, buffer));
}