mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
367 lines
9.8 KiB
367 lines
9.8 KiB
/*****************************************************************************
|
|
*
|
|
* 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;
|
|
}
|