mirror of
https://github.com/open-simh/simtools.git
synced 2026-02-02 23:02:23 +00:00
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.
204 lines
5.3 KiB
C
204 lines
5.3 KiB
C
/* 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));
|
||
}
|