NT4/private/ntos/dd/qic117/0x1103a.c
2020-09-30 17:12:29 +02:00

368 lines
9.8 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.

/*****************************************************************************
*
* COPYRIGHT 1993 - COLORADO MEMORY SYSTEMS, INC.
* ALL RIGHTS RESERVED.
*
******************************************************************************
*
* FILE: \SE\DRIVER\DEVICE\JUMBO\SRC\0X1103A.C
*
* FUNCTION: cqd_ClearInterrupt
*
* PURPOSE:
*
* HISTORY:
* $Log: J:\se.vcs\driver\q117cd\src\0x1103a.c $
*
* Rev 1.5 09 Feb 1995 12:33:06 kurtgodw
* final m8 fixes
*
* Rev 1.4 23 Feb 1994 17:16:12 KEVINKES
* Removed an unreferenced local variable.
*
* Rev 1.3 23 Feb 1994 15:41:06 KEVINKES
* Modified to return a status and to correct problems with
* leaving the FDC in an unknown state.
*
* Rev 1.2 11 Nov 1993 15:20:46 KEVINKES
* Changed calls to cqd_inp and cqd_outp to kdi_ReadPort and kdi_WritePort.
* Modified the parameters to these calls. Changed FDC commands to be
* defines.
*
* Rev 1.1 08 Nov 1993 14:05:30 KEVINKES
* Removed all bit-field structures, removed all enumerated types, changed
* all defines to uppercase, and removed all signed data types wherever
* possible.
*
* Rev 1.0 18 Oct 1993 17:19:30 KEVINKES
* Initial Revision.
*
*****************************************************************************/
#define FCT_ID 0x1103a
#include "include\public\adi_api.h"
#include "include\public\frb_api.h"
#include "include\private\kdi_pub.h"
#include "include\private\cqd_pub.h"
#include "q117cd\include\cqd_defs.h"
#include "q117cd\include\cqd_strc.h"
#include "q117cd\include\cqd_hdr.h"
/*endinclude*/
dStatus cqd_ClearInterrupt
(
/* INPUT PARAMETERS: */
dVoidPtr context,
dBoolean expected_interrupt
/* UPDATE PARAMETERS: */
/* OUTPUT PARAMETERS: */
)
/* COMMENTS: *****************************************************************
*
* DEFINITIONS: *************************************************************/
{
/* DATA: ********************************************************************/
dStatus status=DONT_PANIC; /* dStatus or error condition.*/
dUDWord i;
CqdContextPtr cqd_context;
dUByte reset_byte;
/* CODE: ********************************************************************/
cqd_context = (CqdContextPtr)context;
if ( cqd_context->controller_data.command_has_result_phase ) {
//
// Result phase of previous command. (Note that we can't trust
// the CMD_BUSY bit in the status register to tell us whether
// there's result bytes or not; it's sometimes wrong).
// By reading the first result byte, we reset the interrupt.
// The other result bytes will be read by a thread.
//
if ( ( kdi_ReadPort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.msr )
& (MSR_RQM | MSR_DIO) ) == (MSR_RQM | MSR_DIO) ) {
cqd_context->controller_data.fifo_byte =
kdi_ReadPort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.dr );
#if DBG
DBG_ADD_ENTRY(QIC117SHOWMCMDS, (CqdContextPtr)cqd_context, DBG_FIFO_FDC);
DBG_ADD_ENTRY(QIC117SHOWMCMDS, (CqdContextPtr)cqd_context, cqd_context->controller_data.fifo_byte);
#endif
} else {
status = kdi_Error(ERR_CONTROLLER_STATE_ERROR, FCT_ID, ERR_SEQ_1);
}
} else {
//
// Previous command doesn't have a result phase. To read how it
// completed, issue a sense interrupt command. Don't read
// the result bytes from the sense interrupt; that is the
// responsibility of the calling thread.
//
i = FDC_MSR_RETRIES;
do {
if ((kdi_ReadPort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.msr) &
(MSR_RQM | MSR_DIO)) == MSR_RQM) {
break;
}
kdi_ShortTimer( kdi_wt12us );
} while (--i > 0);
if (i != 0) {
#if DBG
DBG_ADD_ENTRY(QIC117SHOWMCMDS, (CqdContextPtr)cqd_context, DBG_PGM_FDC);
DBG_ADD_ENTRY(QIC117SHOWMCMDS, (CqdContextPtr)cqd_context, FDC_CMD_SENSE_INT);
#endif
kdi_WritePort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.dr,
FDC_CMD_SENSE_INT );
kdi_ShortTimer( kdi_wt12us );
//
// Wait for the controller to ACK the SenseInterrupt command, by
// showing busy. On very fast machines we can end up running
// driver's system-thread before the controller has had time to
// set the busy bit.
//
for (i = FDC_MSR_RETRIES; i; i--) {
if (kdi_ReadPort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.msr) & MSR_CB) {
break;
}
kdi_ShortTimer( kdi_wt12us );
}
}
if (i == 0) {
status = kdi_Error(ERR_CONTROLLER_STATE_ERROR, FCT_ID, ERR_SEQ_1);
}
/* Code no longer valid - Kurt G. - due to ISR sharing
if (!expected_interrupt && (status == DONT_PANIC)) {
//
// This is an unexpected interrupt, so nobody's going to
// read the result bytes. Read them now.
//
cqd_context->controller_data.fifo_byte =
kdi_ReadPort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.dr );
cqd_context->controller_data.fifo_byte =
kdi_ReadPort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.dr );
}
End of no longer functioning code */
}
/* Code no longer functioning - Kurt G. - Due to ISR sharing
if (status == DONT_PANIC) {
cqd_context->controller_data.isr_reentered = 0;
} else {
* Running the floppy (at least on R4000 boxes) we've seen
* examples where the device interrupts, yet it never says
* it *ISN'T* busy. If this ever happens on non-MCA x86 boxes
* it would be ok since we use latched interrupts. Even if
* the device isn't touched so that the line would be pulled
* down, on the latched machine, this ISR wouldn't be called
* again. The normal timeout code for a request would eventually
* reset the controller and retry the request.
*
* On the R4000 boxes and on MCA machines, the floppy is using
* level sensitive interrupts. Therefore if we don't do something
* to lower the interrupt line, we will be called over and over,
* *forever*. This makes it look as though the machine is hung.
* Unless we were lucky enough to be on a multiprocessor, the
* normal timeout code would NEVER get a chance to run because
* the timeout code runs at dispatch level, and we will never
* leave device level.
*
* What we will do is keep a counter that is incremented every
* time we reach this section of code. When the counter goes
* over the threshold we will do a hard reset of the device
* and reset the counter down to zero. The counter will be
* initialized when the device is first initialized. It will
* be set to zero in the other arm of this if, and it will be
* reset to zero by the normal timeout logic.
if (cqd_context->controller_data.isr_reentered > FDC_ISR_RESET_THRESHOLD) {
//
// Reset the controller. This could cause an interrupt
//
cqd_context->controller_data.isr_reentered = 0;
if (!cqd_context->configured) {
cqd_context->selected = dFALSE;
kdi_WritePort( cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.dor,
alloff);
kdi_ShortTimer(kdi_wt10us);
kdi_WritePort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.dor,
dselb);
} else {
if (cqd_context->selected == dTRUE) {
reset_byte =
cqd_context->device_cfg.select_byte;
} else {
reset_byte =
cqd_context->device_cfg.deselect_byte;
}
reset_byte &= 0xfb;
kdi_WritePort( cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.dor,
reset_byte);
kdi_ShortTimer(kdi_wt10us);
reset_byte |= 0x0c;
kdi_WritePort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.dor,
reset_byte);
}
kdi_ShortTimer(kdi_wt500us);
i = FDC_MSR_RETRIES;
do {
if ((kdi_ReadPort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.msr) &
(MSR_RQM | MSR_DIO)) == MSR_RQM) {
break;
}
kdi_ShortTimer( kdi_wt12us );
} while (--i > 0);
if (i != 0) {
kdi_WritePort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.dr,
FDC_CMD_SENSE_INT );
kdi_ShortTimer( kdi_wt12us );
// Wait for the controller to ACK the SenseInterrupt command, by
// showing busy. On very fast machines we can end up running
// driver's system-thread before the controller has had time to
// set the busy bit.
for (i = FDC_MSR_RETRIES; i; i--) {
if (kdi_ReadPort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.msr) & MSR_CB) {
break;
}
kdi_ShortTimer( kdi_wt12us );
}
}
cqd_context->controller_data.fifo_byte =
kdi_ReadPort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.dr );
cqd_context->controller_data.fifo_byte =
kdi_ReadPort(
cqd_context->kdi_context,
cqd_context->controller_data.fdc_addr.dr );
// Let the interrupt settle
kdi_ShortTimer( kdi_wt12us );
} else {
cqd_context->controller_data.isr_reentered++;
}
}
End of Non functioning code */
return status;
}