📄 fl_drver.c
字号:
* Inputs:
* ticks - Fail if more than ticks elapses
*
*
* Returns:
* TRUE if the dma transfer was sucessful.
*
* Description:
* This function is called when the driver is waiting for a dma transfer to
* complete. The transfer was set up by fl_dma_setup().
*
* This routine calls pc_wait_int(ticks) for the floppy to interrupt
* and then verifies that the dma channel has reach terminal count.
* need to do is wait for the floppy interrupt. We seperated the two
*
* Note: In a system using programmed transfer the transfer loop
* would go inside here. The addresses and could would come from
* fl_dma_init().
*
*/
/* DMA registers */
#define STATUS_REGISTER 0x08
#define MASK_REGISTER 0x0a
#define MODE_REGISTER 0x0b
#define FLIPFLOP_REGISTER 0x0c
#define BANK_REGISTER 0x81
/* Channel 2 register bank */
#define ADDRESS_REGISTER 0x04
#define int_REGISTER 0x05
static BOOLEAN fl_waitdma(int ticks) /*__fn__*/
{
byte status;
if (fl_waitint(ticks))
{
/* Check terminal count flag */
status = (byte) INBYTE(STATUS_REGISTER);
if (status & BIT2)
{
return(TRUE);
}
else
{
return(FALSE);
}
}
return(FALSE);
}
/*
* Name:
* fl_dma_init() - Initialize a dma transfer
*
* Summary:
* BOOLEAN fl_dma_init(DMAPTYPE in_address, word length, BOOLEAN reading)
*
* Inputs:
* in_address - Address to transfer data to/from
* length - Length in bytes to transfer
* reading - If TRUE, floppy to memory, else mem to floppy
* Returns:
* TRUE if the setup was successful. FALSE on a boundary wrap.
*
* Description:
* This function is called to set up a dma transfer.
*
* Porting instructions:
* This routine should be ported to support your dma controller. If you are
* using programmed IO the input values should be stored away for use by
* the transfer routine in fl_waitdma()
*/
dword kvtodma(DMAPTYPE in_address)
{
dword laddress;
#if (FLAT_ADDRESSING || IS_MS_PM || IS_BCC_PM || IS_WC_PM || IS_HC_PM)
laddress = (dword) in_address;
#else
laddress = (dword) POINTER_SEGMENT(in_address);
laddress <<= 4;
laddress += (dword) POINTER_OFFSET(in_address);
#endif
return(laddress);
}
static BOOLEAN fl_dma_init(DMAPTYPE in_address, word length, BOOLEAN reading) /*__fn__*/
{
byte dma_page;
byte addr_low;
byte addr_high;
dword laddress;
word *p;
byte mode;
length -= (word)1;
laddress = kvtodma(in_address);
p = (word *) &laddress;
// dma_page = (byte) (*(p+1) & 0xf);
dma_page = (byte) (*(p+1) & 0xff);
addr_high = (byte) ((*p) >> 8);
addr_low = (byte) ((*p) & 0xff);
/* Convert from generic xfer request to dma processor specific */
if (reading)
mode = 0x46; /* SINGLE MODE, READ, CHANNEL 2 */
else
mode = 0x4a; /* SINGLE MODE, WRITE, CHANNEL 2 */
ks_disable();
OUTBYTE(MASK_REGISTER,BIT2|0x02); /* disable channel 2 */
ks_enable();
OUTBYTE(MODE_REGISTER,mode);
/* Write the bank switch register */
OUTBYTE(BANK_REGISTER,dma_page);
/* Write the address */
OUTBYTE(FLIPFLOP_REGISTER,0x00); /* clear flfl before writing address */
/* Write the address. low byte high byte */
OUTBYTE(ADDRESS_REGISTER,addr_low);
OUTBYTE(ADDRESS_REGISTER,addr_high);
/* Write the length. low byte high byte */
OUTBYTE(FLIPFLOP_REGISTER,0x00); /* clear flfl before writing count */
OUTBYTE(int_REGISTER, (byte) (length & 0xff));
OUTBYTE(int_REGISTER, (byte) (length >> 8));
OUTBYTE(MASK_REGISTER,0x02); /* re-enable channel 2 */
return (TRUE);
}
//DM: added conditional to comment out if !PME
#if !defined(PME)
/*
* Name:
* fl_dma_chk() - Returns the number of blocks beyond the current
* addesss in the address's dma page
* Summary:
* word fl_dma_chk(byte far *in_address)
*
*
* Inputs:
* in_address - Address to check
*
*
* Returns:
* The number of blocks beyond the current in the dma page.
*
* Description:
* This function is called when the driver is preparing for a dma transfer.
* It returns the number of blocks left in the page beyond the current
* address.
*
*/
static word fl_dma_chk(DMAPTYPE in_address) /*__fn__*/
{
word utemp;
dword laddress;
laddress = kvtodma(in_address);
utemp = (word) (laddress & 0xffff);
if (utemp == 0)
return(128);
else
{
/* bytes between here and the top */
utemp = (word) (0xffff - utemp);
utemp += (word)1;
return((word)(utemp >> 9));
}
}
#endif // PME
#endif // USE_DMA
/* Register access functions -
*
* The following functions access the the 37c65 floppy disk registers
* We segregated these into simple routines to make it easier on NON-AT
* systems.
*
*
*/
/* Write data rate register */
static void fl_write_drr(byte value) /*__fn__*/
{
OUTBYTE(0x3f7, value);
}
/* Read data rate register */
static byte fl_read_drr() /*__fn__*/
{
return((byte) INBYTE(0x3f7));
}
/* Write to digital output register */
static void fl_write_dor(byte value) /*__fn__*/
{
OUTBYTE(0x3f2, value);
}
/* Write to data register */
static void fl_write_data(byte value) /*__fn__*/
{
OUTBYTE(0x3f5, value);
}
/* Read data register */
static byte fl_read_data() /*__fn__*/
{
return((byte) INBYTE(0x3f5));
}
/* Read master status register */
static byte fl_read_msr() /*__fn__*/
{
return((byte) INBYTE(0x3f4));
}
int ph_first_floppy(void)
{
return(0); /* This can't happen */
}
int ph_last_floppy(void)
{
return(0);
}
#if (!USE_DMA)
int polled_read(byte KS_FAR *buffer, word n, byte cmd)
{
unsigned int timeout2;
word seg_1,offs;
timeout2 = 10;
seg_1 = FP_SEG(buffer);
offs = FP_OFF(buffer);
#if (GNU)
/* Comment out this code so it doesn't make gcc choke.
We could do this with conditional #includes, but GNU preprocessor
chokes anyway
#endif
#if (EBSENV) // This commented stuff gets noticed by ifstrip.
*/ // NOTE: These hacks do NOT allow us to build RTFS
#endif // in our environment under GNU. -Ansel.
__asm
{
cli ; disable interrupts
mov dx, 3f5h ; send cmd to the data port to complete the command block
mov al, cmd
out dx, al ; command now send
push di ; di register needs to be saved under C environment
mov ax, seg_1 ; es is segment of destination buffer
mov es, ax ;
mov di, offs ; di is offset of destination
mov cx, n ; # bytes to transfer. cx is decremented by loop instruction
more:
mov dx, 3f4h ; dx contains main status register address
mov bx,0 ; bx is 0. we'll timeout when it counts backwords to zero
; again
poll:
dec bx ; note: zero-- ==s 0xffff
jnz check ; no timeout. chech the msr for xfer conditions
mov ax, timeout2 ; we hit 0. decrement the second level timeout counter
dec ax ;
jz done ; if 2nd level counter hit zero bail
mov timeout2, ax ; save the decremented second level timer
mov bx,0 ; reset the first level timer
check:
in al, dx ; read the main status refgister
; test bits in the main status register
test al, 10h ; if not BUSY the command hasn't started
jz poll
test al, 80h ; if not RQM it's not ready for io
jz poll
test al, 40h ; if not DIO it isn't in to host mode (probably hosed)
jz poll
test al, 20h ; if not NDMA it isn't in ndam mode (definately hosed)
jz done
; If we get here we're ok. read the data
mov dx, 3f5h ; address of data port
in al, dx ; data to al
mov es:[di], al ; al to the destination buffer
inc di ; update the buffer
loop more ; decrement cx. if non zero go to more
done:
mov n, cx ; move cx to n so we can return it. It should be zero.
; otherwise it is a residual count indicating we broke
; out early
pop di ; restore the di register for the c environment
sti
}
#if (EBSENV) // Please see the notice at the top of this assembly code.
/*
#endif
#if (GNU)
*/
#endif
return(n);
}
int polled_write(byte KS_FAR *buffer, word n, byte cmd)
{
unsigned int timeout2;
word seg_1,offs;
timeout2 = 10;
seg_1 = FP_SEG(buffer);
offs = FP_OFF(buffer);
#if (GNU)
/* Comment out this code so it doesn't make gcc choke.
We could do this with conditional #includes, but that GNU preprocessor
still chokes on it
#endif
#if (EBSENV) // This commented stuff gets noticed by ifstrip.
*/ // NOTE: These hacks do NOT allow us to build RTFS
#endif // in our environment under GNU. -Ansel.
__asm
{
cli ; disable interrupts
mov dx, 3f5h ; send cmd to the data port to complete the command block
mov al, cmd
out dx, al ; command now send
push si ; si register needs to be saved under C environment
mov ax, seg_1 ; es is segment of source buffer
mov es, ax ;
mov si, offs ; si is offset of source
mov cx, n ; # bytes to transfer. cx is decremented by loop instruction
more:
mov dx, 3f4h ; dx contains main status register address
mov bx,0 ; bx is 0. we'll timeout when it counts backwords to zero
; again
poll:
dec bx ; note: zero-- ==s 0xffff
jnz check ; no timeout. chech the msr for xfer conditions
mov ax, timeout2 ; we hit 0. decrement the second level timeout counter
dec ax ;
jz done ; if 2nd level counter hit zero bail
mov timeout2, ax ; save the decremented second level timer
mov bx,0 ; reset the first level timer
check:
in al, dx ; read the main status refgister
; test bits in the main status register
test al, 10h ; if not BUSY the command hasn't started
jz poll
test al, 80h ; if not RQM it's not ready for io
jz poll
test al, 40h ; if DIO it isn't in from host mode (probably hosed)
jnz poll
test al, 20h ; if not NDMA it isn't in ndam mode (definately hosed)
jz done
; If we get here we're ok. write the data
mov al, es:[si] ; source buffer to al
inc si ; update the buffer
mov dx, 3f5h ; address of data port
out dx, al ; command now send
loop more ; decrement cx. if non zero go to more
done:
mov n, cx ; move cx to n so we can return it. It should be zero.
; otherwise it is a residual count indicating we broke
; out early
pop di ; restore the di register for the c environment
sti
}
#if (EBSENV) // Please see the notice at the top of this assembly code.
/*
#endif
#if (GNU)
*/
#endif
return(n);
}
#endif /* (!USE_DMA) */
int floppy_perform_device_ioctl(int driveno, int opcode, PFVOID pargs)
{
DDRIVE *pdr;
DEV_GEOMETRY gc; // used by DEVCTL_GET_GEOMETRY
int size;
byte fltype;
pdr = pc_drno_to_drive_struct(driveno);
if (!pdr)
return (-1);
switch (opcode)
{
/* Getgeometry and format share common code */
case DEVCTL_GET_GEOMETRY:
case DEVCTL_FORMAT:
/* Prepare to return an initialized format parameter structure */
pc_memfill(&gc, sizeof(gc), '\0');
/* Forc
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -