VOID ScsiPortWriteRegisterUshort( IN PUSHORT Register, IN USHORT Value ) /*++ Routine Description: Write to the specificed register address. Arguments: Register - Supplies a pointer to the register address. Value - Supplies the value to be written. Return Value: None --*/ { WRITE_REGISTER_USHORT(Register, Value); }
VOID NTAPI ScsiPortWriteRegisterUshort( IN PUSHORT Register, IN USHORT Value) { WRITE_REGISTER_USHORT(Register, Value); }
VOID NTAPI VideoPortWriteRegisterUshort( PUSHORT Register, USHORT Value) { WRITE_REGISTER_USHORT(Register, Value); }
USHORT HWREG<USHORT>::Write( _In_ USHORT Value ) { volatile USHORT *addr = &m_Value; WRITE_REGISTER_USHORT((PUSHORT)addr, Value); return Value; }
VOID NTAPI LlbHwOmap3TwlWrite(IN UCHAR ChipAddress, IN UCHAR RegisterAddress, IN UCHAR Length, IN PUCHAR Values) { volatile int i = 1000; ULONG j; /* Select chip address */ WRITE_REGISTER_USHORT(0x4807002c, ChipAddress); WRITE_REGISTER_USHORT(0x48070018, Length + 1); /* Enable master transmit mode */ WRITE_REGISTER_USHORT(0x48070024, 0x8601); WRITE_REGISTER_USHORT(0x4807001c, RegisterAddress); /* Loop each byte */ for (j = 0; j < Length; j++) { /* Write the data */ WRITE_REGISTER_USHORT(0x4807001c, Values[j]); } /* Issue stop command */ WRITE_REGISTER_USHORT(0x48070024, 0x8602); for (i = 1000; i > 0; i--); }
VOID vWriteFifoW( VOID* p, ULONG v) { gcFifo--; if (gcFifo < 0) { gcFifo = 0; RIP("Incorrect FIFO wait count"); } WRITE_REGISTER_USHORT(p, (USHORT) v); }
UCHAR NTAPI LlbHwOmap3TwlRead1(IN UCHAR ChipAddress, IN UCHAR RegisterAddress) { volatile int i = 1000; /* Select the register */ LlbHwOmap3TwlWrite(ChipAddress, RegisterAddress, 0, NULL); /* Now read it */ WRITE_REGISTER_USHORT(0x48070024, 0x8401); for (i = 1000; i > 0; i--); return READ_REGISTER_USHORT(0x4807001c); }
VOID HalpResetCirrusChip( VOID ) /*+++ This function resets/loads default values to the Cirrus Chip extended registers for use with extended text mode (80x50) Register values found in the cirrus manual, appendix D5 ---*/ { UCHAR byte; WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen off byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA); WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte | 0x20)); // stop the sequencer // extended sequencer and crtc regs for cirrus WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x1206); // unlock the extended registers WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0007); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x4008); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x5709); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x180a); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x660b); // new modifs WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x3b1b); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x000f); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0016); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x001b); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0007); WRITE_REGISTER_USHORT(VGA_GRAPH_IDX, 0x0009); WRITE_REGISTER_USHORT(VGA_GRAPH_IDX, 0x000a); WRITE_REGISTER_USHORT(VGA_GRAPH_IDX, 0x000b); // end new modifs WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0010); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0011); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0012); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0013); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0018); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0119); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x001a); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x3b1b); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x2f1c); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x301d); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x331e); }
VOID CardDialNumber( IN PHTDSU_ADAPTER Adapter, IN USHORT CardLine, /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */ IN PUCHAR DialString, IN ULONG DialStringLength ) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Functional Description: Place a dial string on the adapter and start the dialing sequence. Parameters: Adapter _ A pointer ot our adapter information structure. CardLine _ Specifies which line to use for the transmit (HTDSU_LINEx_ID). DialString _ A pointer to an ASCII null-terminated string of digits. DialStringLength _ Number of bytes in dial string. Return Values: None ---------------------------------------------------------------------------*/ { DBG_FUNC("CardDialNumber") UINT Index; UINT NumDigits; PUSHORT DialRam; DBG_ENTER(Adapter); ASSERT(READ_REGISTER_USHORT(&Adapter->AdapterRam->TxDataEmpty)); ASSERT(READ_REGISTER_USHORT(&Adapter->AdapterRam->Command) == HTDSU_CMD_NOP); /* // Copy the digits to be dialed onto the adapter. // The adapter interprets phone numbers as high byte is valid digit, // low byte is ignored, the last digit gets bit 15 set. */ DialRam = (PUSHORT) &Adapter->AdapterRam->TxBuffer; for (NumDigits = Index = 0; Index < DialStringLength && *DialString; Index++) { if ((*DialString >= '0') && (*DialString <= '9')) { WRITE_REGISTER_USHORT( DialRam, (USHORT) ((*DialString - '0') << 8) ); DialRam++; /* // Make sure dial string is within the limit of the adapter. */ if (++NumDigits >= HTDSU_MAX_DIALING_DIGITS) { break; } } DialString++; } /* // Set the MSB in the last digit. */ DialRam--; WRITE_REGISTER_USHORT( DialRam, (USHORT) (READ_REGISTER_USHORT(DialRam) | 0x8000) ); /* // Initiate the dial sequence. */ CardDoCommand(Adapter, CardLine, HTDSU_CMD_DIAL); DBG_LEAVE(Adapter); }
NDIS_STATUS CardDoCommand( IN PHTDSU_ADAPTER Adapter, IN USHORT CardLine, /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */ IN USHORT CommandValue ) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Functional Description: This routine routine will execute a command on the card after making sure the previous command has completed properly. Parameters: Adapter _ A pointer ot our adapter information structure. CardLine _ Specifies which line to use for the transmit (HTDSU_LINEx_ID). CommandValue _ HTDSU_CMD_??? command to be executed. Return Values: NDIS_STATUS_SUCCESS NDIS_STATUS_HARD_ERRORS ---------------------------------------------------------------------------*/ { DBG_FUNC("CardDoCommand") ULONG TimeOut = 0; DBG_ENTER(Adapter); DBG_FILTER(Adapter, DBG_PARAMS_ON,("Line=%d, Command=%04X, LineStatus=%Xh\n", CardLine, CommandValue, READ_REGISTER_USHORT(&Adapter->AdapterRam->StatusLine1) )); /* // Wait for command register to go idle - but don't wait too long. // If we timeout here, there's gotta be something wrong with the adapter. */ while ((READ_REGISTER_USHORT(&Adapter->AdapterRam->Command) != HTDSU_CMD_NOP) || (READ_REGISTER_USHORT(&Adapter->AdapterRam->CoProcessorId) != HTDSU_COPROCESSOR_ID)) { if (TimeOut++ > HTDSU_SELFTEST_TIMEOUT) { DBG_ERROR(Adapter,("Timeout waiting for %04X command to clear\n", READ_REGISTER_USHORT(&Adapter->AdapterRam->Command))); /* // Ask for reset, and disable interrupts until we get it. */ Adapter->NeedReset = TRUE; Adapter->InterruptEnableFlag = HTDSU_INTR_DISABLE; CardDisableInterrupt(Adapter); return (NDIS_STATUS_HARD_ERRORS); } NdisStallExecution(_100_MICROSECONDS); } DBG_NOTICE(Adapter,("Timeout=%d waiting to submit %04X\n", TimeOut, CommandValue)); /* // Before starting a reset command, we clear the the co-processor ID // which then gets set to the proper value when the reset is complete. */ if (CommandValue == HTDSU_CMD_RESET) { WRITE_REGISTER_USHORT(&Adapter->AdapterRam->CoProcessorId, 0); } /* // Send the command to the adapter. */ WRITE_REGISTER_USHORT( &Adapter->AdapterRam->Command, (USHORT) (CommandValue + CardLine) ); DBG_LEAVE(Adapter); return (NDIS_STATUS_SUCCESS); }
VOID DigiServiceEvent( IN PDIGI_CONTROLLER_EXTENSION ControllerExt, IN USHORT Ein, IN USHORT Eout ) /*++ Routine Description: Arguments: Return Value: --*/ { const USHORT Emax = 0x03FC; DigiDump( (DIGIFLOW|DIGIEVENT), ("Entering DigiServiceEvent\n") ); // Event registers should be in range and DWORD-aligned. ASSERT( Ein <= Emax && (Ein & 3) == 0 ); ASSERT( Eout <= Emax && (Eout & 3) == 0 ); DigiDump( DIGIEVENT, ("--------- Ein(0x%.4x) != Eout(0x%.4x)\n", Ein, Eout ) ); for( ; Eout != Ein ; Eout += 4, Eout &= Emax ) { PDIGI_DEVICE_EXTENSION DeviceExt; PFEP_EVENT pEvent; FEP_EVENT Event; ULONG EventReason; pEvent = (PFEP_EVENT)(ControllerExt->VirtualAddress + ControllerExt->EventQueue.Offset + Eout ); EnableWindow( ControllerExt, ControllerExt->EventQueue.Window ); READ_REGISTER_BUFFER_UCHAR( (PUCHAR)pEvent, (PUCHAR)&Event, sizeof(Event) ); DisableWindow( ControllerExt ); if( (Event.Channel <= 0xDF) && (Event.Channel < ControllerExt->NumberOfPorts) ) { DeviceExt = ControllerExt->DeviceObjectArray[Event.Channel]->DeviceExtension; } else // bad command? { DeviceExt = NULL; DigiDump( DIGIEVENT, ("Event on unknown channel %d (flags = 0x%.2x), ignored\n", Event.Channel, Event.Flags) ); continue; } DigiDump( DIGIEVENT, ("--------- Channel = %d\tFlags = 0x%.2x\n" "--------- Current = 0x%.2x\tPrev. = 0x%.2x\n", Event.Channel, Event.Flags, Event.CurrentModem, Event.PreviousModem) ); // // OK, let's process the event // if( Event.Flags & ~(FEP_ALL_EVENT_FLAGS) ) { DigiDump( DIGIERRORS, ("Unknown event queue flag 0x%.2x\n", Event.Flags & ~(FEP_ALL_EVENT_FLAGS) ) ); // Process the event bits that we *do* understand. } // Modem signals are always processed, regardless of whether the port is open. if( Event.Flags & FEP_MODEM_CHANGE_SIGNAL ) { DigiDump( (DIGIMODEM|DIGIEVENT|DIGIWAIT), ("--------- Modem Change Event (%s:%d)\n", __FILE__, __LINE__ ) ); KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess ); DigiDump( (DIGIMODEM|DIGIWAIT), (" CurrentModem = 0x%x\tPreviousModem = 0x%x\n", Event.CurrentModem, Event.PreviousModem )); DeviceExt->CurrentModemSignals = Event.CurrentModem; KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess ); } // If the port isn't open, don't bother with the rest. if( DeviceExt->DeviceState != DIGI_DEVICE_STATE_OPEN ) { // If we might return to OPEN, don't touch anything! if( DeviceExt->DeviceState != DIGI_DEVICE_STATE_CLEANUP) { if( Event.Flags & (FEP_RX_PRESENT | FEP_RECEIVE_BUFFER_OVERRUN | FEP_UART_RECEIVE_OVERRUN) ) { PFEP_CHANNEL_STRUCTURE ChInfo; FlushReceiveBuffer( ControllerExt, DeviceExt ); ChInfo = (PFEP_CHANNEL_STRUCTURE)(ControllerExt->VirtualAddress + DeviceExt->ChannelInfo.Offset); // Notify us when more data comes in. EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window ); WRITE_REGISTER_UCHAR( &ChInfo->idata, TRUE ); DisableWindow( ControllerExt ); } // Don't flush transmit (might kill end of data). } continue; } // Reset event notifications. EventReason = 0; if( Event.Flags & FEP_EV_BREAK ) { EventReason |= SERIAL_EV_BREAK; KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess ); DeviceExt->ErrorWord |= SERIAL_ERROR_BREAK; KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess ); } if( (Event.Flags & (FEP_TX_LOW | FEP_TX_EMPTY) ) ) { PLIST_ENTRY WriteQueue; #if DBG switch( Event.Flags & (FEP_TX_LOW | FEP_TX_EMPTY) ) { case FEP_TX_LOW: DigiDump( (DIGIEVENT|DIGIWRITE), ("%s:\tTXLOW event\n", DeviceExt->DeviceDbgString) ); break; case FEP_TX_EMPTY: DigiDump( (DIGIEVENT|DIGIWRITE), ("%s:\tTXEMPTY event\n", DeviceExt->DeviceDbgString) ); break; default: DigiDump( (DIGIEVENT|DIGIWRITE), ("%s:\tTXLOW and TXEMPTY events\n", DeviceExt->DeviceDbgString) ); break; } #endif WriteQueue = &DeviceExt->WriteQueue; KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess ); if( !IsListEmpty( WriteQueue ) ) { PIRP Irp; Irp = CONTAINING_RECORD( WriteQueue->Flink, IRP, Tail.Overlay.ListEntry ); if( Irp->IoStatus.Information != MAXULONG ) { PIO_STACK_LOCATION IrpSp; IrpSp = IoGetCurrentIrpStackLocation( Irp ); if( IrpSp->MajorFunction == IRP_MJ_WRITE || ( IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL && Irp->IoStatus.Information == 0 ) ) { DigiDump( DIGIEVENT, ("--------- WriteQueue list NOT empty\n") ); if( IrpSp->MajorFunction == IRP_MJ_WRITE ) { ASSERT( Irp->IoStatus.Information < IrpSp->Parameters.Write.Length ); } else { ASSERT( IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_IMMEDIATE_CHAR || IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_XOFF_COUNTER ); } if( WriteTxBuffer( DeviceExt ) == STATUS_SUCCESS ) { KIRQL OldIrql = DISPATCH_LEVEL; DigiDump( DIGIEVENT, ("--------- Write complete. Successfully completing Irp.\n" "--------- #bytes completing = %d\n", Irp->IoStatus.Information ) ); DIGI_INC_REFERENCE( Irp ); DigiTryToCompleteIrp( DeviceExt, &OldIrql, STATUS_SUCCESS, WriteQueue, NULL, &DeviceExt->WriteRequestTotalTimer, StartWriteRequest ); goto WriteDone; // skip unlock } // WriteTxBuffer returned SUCCESS } // IRP is eligible for WriteTxBuffer } // IRP started KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess ); WriteDone:; } else // empty(WQ) { DigiDump( DIGIEVENT, ("--------- WriteQueue was empty\n") ); if( Event.Flags & FEP_TX_EMPTY ) EventReason |= SERIAL_EV_TXEMPTY; KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess ); } } // FEP_TX_LOW | FEP_TX_EMPTY if( Event.Flags & FEP_RX_PRESENT ) { PLIST_ENTRY ReadQueue; PFEP_CHANNEL_STRUCTURE ChInfo; USHORT Rin, Rout, Rmax, RxSize; DigiDump( DIGIEVENT, ("--------- Rcv Data Present Event: (%s:%d)\n", __FILE__, __LINE__ ) ); GetReceivedData:; ChInfo = (PFEP_CHANNEL_STRUCTURE)(ControllerExt->VirtualAddress + DeviceExt->ChannelInfo.Offset); KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess ); EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window ); Rout = READ_REGISTER_USHORT( &ChInfo->rout ); Rin = READ_REGISTER_USHORT( &ChInfo->rin ); Rmax = READ_REGISTER_USHORT( &ChInfo->rmax ); DisableWindow( ControllerExt ); if( (DeviceExt->WaitMask & SERIAL_EV_RXCHAR) && (DeviceExt->PreviousRxChar != (ULONG)Rin) ) { EventReason |= SERIAL_EV_RXCHAR; } if( (DeviceExt->WaitMask & SERIAL_EV_RXFLAG) && (DeviceExt->UnscannedRXFLAGPosition != (ULONG)Rin) ) { if( ScanReadBufferForSpecialCharacter( DeviceExt, DeviceExt->SpecialChars.EventChar ) ) { EventReason |= SERIAL_EV_RXFLAG; } } // // Determine if we are waiting to notify a 80% receive buffer // full. // // NOTE: I assume the controller will continue to notify // us that data is still in the buffer, even if // we don't take the data out of the controller's // buffer. // if( (DeviceExt->WaitMask & SERIAL_EV_RX80FULL) && !(DeviceExt->HistoryWait & SERIAL_EV_RX80FULL) ) // notification is already pending { // // Okay, is the receive buffer 80% or more full?? // RxSize = (Rin - Rout) & Rmax; if( RxSize ) { if( DeviceExt->SpecialFlags & DIGI_SPECIAL_FLAG_FAST_RAS ) { if( RxSize >= DeviceExt->ReceiveNotificationLimit ) { EventReason |= SERIAL_EV_RX80FULL; } } else // not RAS { // Perform 32-bit math to avoid roundoff errors. if( RxSize >= (USHORT) ( ((ULONG)Rmax + 1UL) * 8UL / 10UL) ) { EventReason |= SERIAL_EV_RX80FULL; } else { USHORT RxHighWater; EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window ); RxHighWater = READ_REGISTER_USHORT( &ChInfo->rhigh ); DisableWindow( ControllerExt ); // If flow control is engaged, trigger the event (we won't get any more data). if( RxSize >= RxHighWater - 1 ) { EventReason |= SERIAL_EV_RX80FULL; } } } // not RAS } // if data } // RX80FULL ReadQueue = &DeviceExt->ReadQueue; if( !IsListEmpty( ReadQueue ) ) { PIRP Irp; Irp = CONTAINING_RECORD( ReadQueue->Flink, IRP, Tail.Overlay.ListEntry ); if( DeviceExt->ReadStatus == STATUS_PENDING && Irp->IoStatus.Information != MAXULONG ) // not started yet { KIRQL OldIrql = DISPATCH_LEVEL; // Hold IRP across lock drop in ReadRxBuffer:ProcessSlowRead:DigiSatisfyWait. DIGI_INC_REFERENCE( Irp ); if( STATUS_SUCCESS == ReadRxBuffer( DeviceExt, &OldIrql ) ) { #if DBG if( DigiDebugLevel & DIGIRXTRACE ) { PUCHAR Temp; ULONG i; Temp = Irp->AssociatedIrp.SystemBuffer; DigiDump( DIGIRXTRACE, ("Read buffer contains: %s", DeviceExt->DeviceDbgString) ); for( i = 0; i < Irp->IoStatus.Information; i++ ) { if( (i & 15) == 0 ) DigiDump( DIGIRXTRACE, ( "\n\t") ); DigiDump( DIGIRXTRACE, ( "-%02x", Temp[i]) ); } DigiDump( DIGIRXTRACE, ("\n") ); } #endif // // We have satisfied this current request, so lets // complete it. // DigiDump( DIGIEVENT, ("--------- Read complete. Successfully completing Irp.\n") ); DigiDump( DIGIEVENT, ("--------- #bytes completing = %d\n", Irp->IoStatus.Information ) ); DeviceExt->ReadStatus = SERIAL_COMPLETE_READ_COMPLETE; DigiTryToCompleteIrp( DeviceExt, &OldIrql, STATUS_SUCCESS, ReadQueue, &DeviceExt->ReadRequestIntervalTimer, &DeviceExt->ReadRequestTotalTimer, StartReadRequest ); goto ReadDone; // skip DEC and unlock } // else ReadRxBuffer != SUCCESS DIGI_DEC_REFERENCE( Irp ); } // else ReadStatus != STATUS_PENDING || IRP not started KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess ); ReadDone:; } else // empty(RQ) { PSERIAL_XOFF_COUNTER Xc; // // We don't have an outstanding read request, so make sure // we reset the IDATA flag on the controller. // ChInfo = (PFEP_CHANNEL_STRUCTURE)(ControllerExt->VirtualAddress + DeviceExt->ChannelInfo.Offset); EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window ); WRITE_REGISTER_UCHAR( &ChInfo->idata, TRUE ); DisableWindow( ControllerExt ); DigiDump( DIGIEVENT, ("--------- No outstanding read IRP's to place received data.\n") ); DeviceExt->PreviousRxChar = (ULONG)Rin; // The perception of receive data might complete an XOFF_COUNTER on the WriteQueue. // Keep track of what we've eaten via XcPreview to avoid counting bytes twice (in ReadRxBuffer). Xc = DeviceExt->pXoffCounter; if( Xc ) { RxSize = (Rin - Rout) & Rmax; if( RxSize < Xc->Counter ) { DigiDump( (DIGIWRITE|DIGIDIAG1), ("IDATA reduced XOFF_COUNTER\n") ); Xc->Counter -= RxSize; DeviceExt->XcPreview += RxSize; } else { // XOFF_COUNTER is complete. KIRQL OldIrql = DISPATCH_LEVEL; #if DBG Xc->Counter = 0; // Looks a little nicer... #endif DigiDump( (DIGIWRITE|DIGIDIAG1), ("IDATA on empty(RQ) is completing XOFF_COUNTER\n") ); DigiTryToCompleteIrp( DeviceExt, &OldIrql, STATUS_SUCCESS, &DeviceExt->WriteQueue, NULL, &DeviceExt->WriteRequestTotalTimer, StartWriteRequest ); goto XcDone; // skip unlock } } KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess ); XcDone:; } } // FEP_RX_PRESENT if( Event.Flags & FEP_MODEM_CHANGE_SIGNAL ) { ULONG WaitMask; UCHAR ChangedModemState; ChangedModemState = Event.CurrentModem ^ Event.PreviousModem; KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess ); WaitMask = DeviceExt->WaitMask; DigiDump( (DIGIMODEM|DIGIEVENT|DIGIWAIT), ("--------- Modem Change Event (%s:%d)\t", " ChangedModemState = 0x%x\n", ChangedModemState, __FILE__, __LINE__ ) ); if( (WaitMask & SERIAL_EV_CTS) && (ControllerExt->ModemSignalTable[CTS_SIGNAL] & ChangedModemState) ) { EventReason |= SERIAL_EV_CTS; } if( (WaitMask & SERIAL_EV_DSR) && (ControllerExt->ModemSignalTable[DSR_SIGNAL] & ChangedModemState) ) { EventReason |= SERIAL_EV_DSR; } if( (WaitMask & SERIAL_EV_RLSD) && (ControllerExt->ModemSignalTable[DCD_SIGNAL] & ChangedModemState) ) { EventReason |= SERIAL_EV_RLSD; } if( (WaitMask & SERIAL_EV_RING) && (ControllerExt->ModemSignalTable[RI_SIGNAL] & ChangedModemState) ) { EventReason |= SERIAL_EV_RING; } if( DeviceExt->EscapeChar ) { UCHAR MSRByte, CurrentModemSignals; if( DeviceExt->PreviousMSRByte ) DigiDump( DIGIERRORS, (" PreviousMSRByte != 0\n") ); MSRByte = 0; if( ControllerExt->ModemSignalTable[CTS_SIGNAL] & ChangedModemState ) { MSRByte |= SERIAL_MSR_DCTS; } if( ControllerExt->ModemSignalTable[DSR_SIGNAL] & ChangedModemState ) { MSRByte |= SERIAL_MSR_DDSR; } if( ControllerExt->ModemSignalTable[RI_SIGNAL] & ChangedModemState ) { MSRByte |= SERIAL_MSR_TERI; } if( ControllerExt->ModemSignalTable[DCD_SIGNAL] & ChangedModemState ) { MSRByte |= SERIAL_MSR_DDCD; } CurrentModemSignals = DeviceExt->CurrentModemSignals; if( ControllerExt->ModemSignalTable[CTS_SIGNAL] & CurrentModemSignals ) { MSRByte |= SERIAL_MSR_CTS; } if( ControllerExt->ModemSignalTable[DSR_SIGNAL] & CurrentModemSignals ) { MSRByte |= SERIAL_MSR_DSR; } if( ControllerExt->ModemSignalTable[RI_SIGNAL] & CurrentModemSignals ) { MSRByte |= SERIAL_MSR_RI; } if( ControllerExt->ModemSignalTable[DCD_SIGNAL] & CurrentModemSignals ) { MSRByte |= SERIAL_MSR_DCD; } if( !IsListEmpty( &DeviceExt->ReadQueue ) ) { PIRP Irp; PIO_STACK_LOCATION IrpSp; Irp = CONTAINING_RECORD( DeviceExt->ReadQueue.Flink, IRP, Tail.Overlay.ListEntry ); IrpSp = IoGetCurrentIrpStackLocation( Irp ); if( (IrpSp->Parameters.Read.Length - Irp->IoStatus.Information) > 3 ) { PUCHAR ReadBuffer; ReadBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer + Irp->IoStatus.Information; ReadBuffer[0] = DeviceExt->EscapeChar; ReadBuffer[1] = SERIAL_LSRMST_MST; ReadBuffer[2] = MSRByte; Irp->IoStatus.Information += 3; DeviceExt->PreviousMSRByte = 0; DigiDump( DIGIMODEM, (" CurrentModemSignals = 0x%x\n" " ChangedModemState = 0x%x\n" " MSRByte = 0x%x\n", DeviceExt->CurrentModemSignals, ChangedModemState, MSRByte) ); } else { DigiDump( (DIGIMODEM|DIGIERRORS), ("Insufficient read IRP space available to record modem status change!\n") ); DeviceExt->PreviousMSRByte = MSRByte; } } else { DigiDump( (DIGIMODEM|DIGIERRORS), ("No read IRP in which to record modem status change!\n") ); DeviceExt->PreviousMSRByte = MSRByte; } KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess ); // // We need to read any data which may be available. // Event.Flags &= ~FEP_MODEM_CHANGE_SIGNAL; goto GetReceivedData; } else { KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess ); } } // FEP_MODEM_CHANGE_SIGNAL if( Event.Flags & FEP_RECEIVE_BUFFER_OVERRUN ) { KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess ); DeviceExt->ErrorWord |= SERIAL_ERROR_QUEUEOVERRUN; InterlockedIncrement(&DeviceExt->PerfData.BufferOverrunErrorCount); KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess ); } if( Event.Flags & FEP_UART_RECEIVE_OVERRUN ) { KeAcquireSpinLockAtDpcLevel( &DeviceExt->ControlAccess ); DeviceExt->ErrorWord |= SERIAL_ERROR_OVERRUN; InterlockedIncrement(&DeviceExt->PerfData.SerialOverrunErrorCount); KeReleaseSpinLockFromDpcLevel( &DeviceExt->ControlAccess ); } if( EventReason ) DigiSatisfyEvent( ControllerExt, DeviceExt, EventReason ); } // // Regardless of whether we processed the event, make sure we forward // the event out pointer. // EnableWindow( ControllerExt, ControllerExt->Global.Window ); WRITE_REGISTER_USHORT( (PUSHORT)((PUCHAR)ControllerExt->VirtualAddress+FEP_EOUT), Eout ); DisableWindow( ControllerExt ); DigiDump( (DIGIFLOW|DIGIEVENT), ("Exiting DigiServiceEvent\n") ); } // DigiServiceEvent
VOID KdpWriteIoSpaceExtended ( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ) /*++ Routine Description: This function is called in response of a read io space extended state manipulation message. Its function is to read system io locations. Arguments: m - Supplies the state manipulation message. AdditionalData - Supplies any additional data for the message. Context - Supplies the current context. Return Value: None. --*/ { PDBGKD_READ_WRITE_IO_EXTENDED64 a = &m->u.ReadWriteIoExtended; ULONG Length; STRING MessageHeader; PUCHAR b; PUSHORT s; PULONG l; ULONG BusNumber; ULONG AddressSpace; ULONG SavedAddressSpace; PHYSICAL_ADDRESS IoAddress; ULONG DataSize; PHYSICAL_ADDRESS TranslatedAddress; INTERFACE_TYPE InterfaceType; ULONG Value; MessageHeader.Length = sizeof(*m); MessageHeader.Buffer = (PCHAR)m; ASSERT(AdditionalData->Length == 0); m->ReturnStatus = STATUS_SUCCESS; InterfaceType = a->InterfaceType; BusNumber = a->BusNumber; AddressSpace = SavedAddressSpace = a->AddressSpace; IoAddress.QuadPart = (ULONG_PTR)a->IoAddress; DataSize = a->DataSize; Value = a->DataValue; // // Translate the bus address to the physical system address // or QVA. // if( !HalTranslateBusAddress( InterfaceType, BusNumber, IoAddress, &AddressSpace, &TranslatedAddress ) ){ m->ReturnStatus = STATUS_INVALID_PARAMETER; goto SendWriteIoSpaceExtendedResponse; } // // N.B. - for the moment we will only support QVAs ie. when AddressSpace // is one. It may be in later systems that we will have to // check the address space, map it, perform the virtual read // unmap, and then return the data - only we will have to be // careful about what Irql we are to make sure the memory mgmt // stuff will all work // if( !AddressSpace ){ m->ReturnStatus = STATUS_INVALID_PARAMETER; goto SendWriteIoSpaceExtendedResponse; } // // Do the IO space read using the appropriate HAL routines based upon // the original address space and the data size requested. // if( !SavedAddressSpace ){ // // Memory (buffer) space on the bus // switch( DataSize ){ case 1: WRITE_REGISTER_UCHAR( (PUCHAR)TranslatedAddress.QuadPart, (UCHAR)Value ); break; case 2: WRITE_REGISTER_USHORT( (PUSHORT)TranslatedAddress.QuadPart, (USHORT)Value ); break; case 4: WRITE_REGISTER_ULONG( (PULONG)TranslatedAddress.QuadPart, Value ); break; default: m->ReturnStatus = STATUS_INVALID_PARAMETER; } } else { // // I/O space on the bus // switch( DataSize ){ case 1: WRITE_PORT_UCHAR( (PUCHAR)TranslatedAddress.QuadPart, (UCHAR)Value ); break; case 2: WRITE_PORT_USHORT( (PUSHORT)TranslatedAddress.QuadPart, (USHORT)Value); break; case 4: WRITE_PORT_ULONG( (PULONG)TranslatedAddress.QuadPart, Value ); break; default: m->ReturnStatus = STATUS_INVALID_PARAMETER; } } SendWriteIoSpaceExtendedResponse: KdpSendPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, NULL ); }
VOID HalpInitializeVGADisplay( TEXT_MODE TextMode ) { static UCHAR _80x50_crt_regs [MAX_CRT] = { // 80x50 text mode 0x5f, 0x4f, 0x50, 0x82, 0x55, // cr0 - cr4 0x81, 0xBF, 0x1f, 0x0, 0x47, // cr9 - 7 lines per char 0x20, 0x00, 0x00, 0x00, 0x00, // cra - cursor off 0x00, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, 0xff }; static UCHAR _132x50_crt_regs [MAX_CRT] = { // 132x50 text mode 0xa0, 0x83, 0x84, 0x83, 0x8a, // cr0 - cr4 0x9e, 0xBF, 0x1f, 0x0, 0x47, // cr9 - 7 lines per char 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x85, 0x8f, 0x42, 0x1f, 0x95, 0xa5, 0xa3, 0xff }; static UCHAR default_graph_regs[GRAPH_MAX] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff }; static UCHAR default_pal_regs[MAX_PALETTE] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x7, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3d, 0x3e, 0x3f, 0x08, 0x00, 0x0f, 0x00, 0x00 }; int i; UCHAR byte; // reset ATC FlipFlop byte = READ_REGISTER_UCHAR(VGA_ATC_FF); WRITE_REGISTER_UCHAR(VGA_ATC_DATA, 0); // Disable palette // stop the sequencer WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0100); if (TextMode == TEXT_132x50) { // external clock (40MHz) WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0xAF); } else { // COLOR registers , enable RAM, 25 MHz (???) 400 Lines, if (HalpVideoChip == VGA_P9100) { WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x67) ; // 28.322 Mhz } else { WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x63) ; // 25,175 MHz (don't use with P9100). } } // Select the timing sequencer values // 8 dot/char WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0101); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0302); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0003); WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0204); // start the sequencer WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0300); // Unprotect CRT regs and program them WRITE_REGISTER_USHORT(VGA_CRT_IDX , 0x0011); for(i=0; i<MAX_CRT; i++) { WRITE_REGISTER_UCHAR(VGA_CRT_IDX, i); if (TextMode == TEXT_132x50){ WRITE_REGISTER_UCHAR(VGA_CRT_DATA, _132x50_crt_regs[i]); } else { WRITE_REGISTER_UCHAR(VGA_CRT_DATA, _80x50_crt_regs[i]); } } DownLoadVGAFont(); HalpDisplayWidth = (TextMode == TEXT_132x50) ? 132 : 80; HalpDisplayText = 50; HalpClearVGADisplay(); i = READ_REGISTER_UCHAR(VGA_ATC_FF); // Reset attr FF if (!HalpFirstBoot) { // // if this is not the First Boot // i.e. an Bugcheck; we have to setup // the Attribute and colors of the VGA PART // for(i=0; i<GRAPH_MAX; i++) { WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX , i); WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, default_graph_regs[i]); } for(i=0; i<MAX_PALETTE; i++) { // PALETTE (ATC) WRITE_REGISTER_UCHAR(VGA_ATC_IDX , i); WRITE_REGISTER_UCHAR(VGA_ATC_DATA, default_pal_regs[i]); } } WRITE_REGISTER_UCHAR(VGA_DAC_MASK , 0xff); // // set the 16 base colors for text mode in the DAC // WRITE_REGISTER_UCHAR(VGA_DAC_WRITE_INDEX, 0x00); for(i=0; i<48; i++) { WRITE_REGISTER_UCHAR(VGA_DAC_DATA, base_colors[i]); } WRITE_REGISTER_UCHAR(VGA_ATC_IDX, 0x20); WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen on byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA); WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte & 0xdf)); // in the sequencer }
VOID HalpVGASetup( VOID ) /*++ Routine Description: This routine initializes a VGA based Graphic card Arguments: None. Return Value: None. --*/ { UCHAR byte; switch (HalpVideoBoard){ case S3_GENERIC_VLB: case CIRRUS_GENERIC_VLB: case VGA_GENERIC_VLB: case P9100_WEITEK: // // N.B. // on an SNI desktop model the VL I/O space is transparent, so // acces in the normal Backplane area results in correct values // the minitower instead, does not decode all VL signals correct, // so ther is an EXTRA I/O space for accessing VL I/O (0x1exxxxxx) // this is handled in the definition of VESA_IO in SNIdef.h // HalpVGAControlBase = (HalpIsRM200) ? (PVOID)HalpEisaControlBase : (PVOID)VESA_IO; VideoBuffer = ( PUSHORT)( VESA_BUS + 0xb8000); FontBuffer = ( PUCHAR )( VESA_BUS + 0xa0000); break; case CIRRUS_ONBOARD: HalpVGAControlBase = (PVOID)HalpOnboardControlBase; VideoBuffer = ( PUSHORT)( RM200_ONBOARD_MEMORY + 0xb8000); FontBuffer = ( PUCHAR )( RM200_ONBOARD_MEMORY + 0xa0000); break; case S3_GENERIC: case CIRRUS_GENERIC: case VGA_GENERIC: default: HalpVGAControlBase = (PVOID)HalpEisaControlBase; VideoBuffer = ( PUSHORT)( EISA_MEMORY_BASE + 0xb8000); FontBuffer = ( PUCHAR )( EISA_MEMORY_BASE + 0xa0000); break; } // // if "only" VGA is detected look for an S3 or cirrus chip (VGA ON ATBUS) // if the firmware detects an S3 chip, look if this is an 805i (interleave) // if ((HalpVideoChip == VGA) || (HalpVideoChip == S3)){ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x1206); // look for Cirrus chips byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA); // read it back if (byte != 0x12) { // no cirrus WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x4838); // unlock the S3 regs WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa539); // Unlock the SC regs WRITE_REGISTER_UCHAR(VGA_CRT_IDX, 0x30); // look for s3 chip id byte = READ_REGISTER_UCHAR(VGA_CRT_DATA) ; // look only for major id switch (byte & 0xf0){ case 0xa0: // 801/805 chipset if (byte == 0xa8) { // the new 805i (interleave) // DebugPrint(("HAL: Found the new 805i Chip resetting to 805 mode\n")); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0053); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0067); } case 0x80: case 0x90: // DebugPrint(("HAL: Found S3 Chip set - Chip id 0x%x\n",byte)); HalpVideoChip = S3; WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0038); // lock s3 regs WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0039); // lock more s3 regs break; default: DebugPrint(("HAL: This seems to be no S3 Chip\n")); } } else { // this may be an cirrus WRITE_REGISTER_UCHAR(VGA_CRT_IDX, 0x27); // cirrus id reg byte = READ_REGISTER_UCHAR(VGA_CRT_DATA); if ((byte & 0xe0) == 0x80) { // look for 100xxxxx // DebugPrint(("HAL: Found Cirrus Chip set - Chip id 0x%x\n",byte)); HalpVideoChip = CIRRUS; WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0006); // lock Cirrus extensions } } } switch (HalpVideoChip) { case VGA_P9000: HalpResetP9000(); // // we have programmed the clock into register 0 of the ICD2061, so // select it via the VGA_MISC register // // WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0xa3); break; case S3: HalpResetS3Chip(); break; case CIRRUS: HalpResetCirrusChip(); break; case VGA_P9100: HalpResetP9100(); break; default: ; } HalpInitializeVGADisplay(TEXT_80x50); // // Initialize the current display column, row, and ownership values. // HalpColumn = 0; HalpRow = 0; HalpDisplayOwnedByHal = TRUE; return; }
VOID KdpWriteIoSpace ( IN PDBGKD_MANIPULATE_STATE m, IN PSTRING AdditionalData, IN PCONTEXT Context ) /*++ Routine Description: This function is called in response of a write io space state manipulation message. Its function is to write to system io locations. Arguments: m - Supplies the state manipulation message. AdditionalData - Supplies any additional data for the message. Context - Supplies the current context. Return Value: None. --*/ { PDBGKD_READ_WRITE_IO a = &m->u.ReadWriteIo; STRING MessageHeader; PUCHAR b; PUSHORT s; PULONG l; MessageHeader.Length = sizeof(*m); MessageHeader.Buffer = (PCHAR)m; ASSERT(AdditionalData->Length == 0); m->ReturnStatus = STATUS_SUCCESS; // // Check Size and Alignment // switch ( a->DataSize ) { case 1: b = (PUCHAR)MmDbgWriteCheck(a->IoAddress); if ( b ) { WRITE_REGISTER_UCHAR(b,(UCHAR)a->DataValue); } else { m->ReturnStatus = STATUS_ACCESS_VIOLATION; } break; case 2: if ((ULONG)a->IoAddress & 1 ) { m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT; } else { s = (PUSHORT)MmDbgWriteCheck(a->IoAddress); if ( s ) { WRITE_REGISTER_USHORT(s,(USHORT)a->DataValue); } else { m->ReturnStatus = STATUS_ACCESS_VIOLATION; } } break; case 4: if ((ULONG)a->IoAddress & 3 ) { m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT; } else { l = (PULONG)MmDbgWriteCheck(a->IoAddress); if ( l ) { WRITE_REGISTER_ULONG(l,a->DataValue); } else { m->ReturnStatus = STATUS_ACCESS_VIOLATION; } } break; default: m->ReturnStatus = STATUS_INVALID_PARAMETER; } KdpSendPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, NULL ); }
VOID NTAPI LlbHwOmap3LcdInitialize(VOID) { /* * N.B. The following initialization sequence took about 12 months to figure * out. * This means if you are glancing at it and have no idea what on Earth * could possibly be going on, this is *normal*. * Just trust that this turns on the LCD. * And be thankful all you ever have to worry about is Java and HTML. */ /* Turn on the functional and interface clocks in the entire PER domain */ WRITE_REGISTER_ULONG(0x48005000, 0x3ffff); /* Functional clocks */ WRITE_REGISTER_ULONG(0x48005010, 0x3ffff); /* Interface clocks */ /* Now that GPIO Module 3 is on, send a reset to the LCD panel on GPIO 96 */ WRITE_REGISTER_ULONG(0x49054034, 0); /* FIXME: Enable all as output */ WRITE_REGISTER_ULONG(0x49054094, 0xffffffff); /* FIXME: Output on all gpios */ /* Now turn on the functional and interface clocks in the CORE domain */ WRITE_REGISTER_ULONG(0x48004a00, 0x03fffe29); /* Functional clocks */ WRITE_REGISTER_ULONG(0x48004a10, 0x3ffffffb); /* Interface clocks */ /* The HS I2C interface is now on, configure it */ WRITE_REGISTER_USHORT(0x48070024, 0x0); /* Disable I2c */ WRITE_REGISTER_USHORT(0x48070030, 0x17); /* Configure clock divider */ WRITE_REGISTER_USHORT(0x48070034, 0xd); /* Configure clock scaler */ WRITE_REGISTER_USHORT(0x48070038, 0xf); /* Configure clock scaler */ WRITE_REGISTER_USHORT(0x48070020, 0x215); /* Configure clocks and idle */ WRITE_REGISTER_USHORT(0x4807000c, 0x636f); /* Select wakeup bits */ WRITE_REGISTER_USHORT(0x48070014, 0x4343); /* Disable DMA */ WRITE_REGISTER_USHORT(0x48070024, 0x8000); /* Enable I2C */ /* * Set the VPLL2 to cover all device groups instead of just P3. * This essentially enables the VRRTC to power up the LCD panel. */ LlbHwOmap3TwlWrite1(0x4B, 0x8E, 0xE0); /* VPLL2 runs at 1.2V by default, so we need to reprogram to 1.8V for DVI */ LlbHwOmap3TwlWrite1(0x4B, 0x91, 0x05); /* Set GPIO pin 7 on the TWL4030 as an output pin */ LlbHwOmap3TwlWrite1(0x49, 0x9B, 0x80); /* Set GPIO pin 7 signal on the TWL4030 ON. This powers the LCD backlight */ LlbHwOmap3TwlWrite1(0x49, 0xA4, 0x80); /* Now go on the McSPI interface and program it on for the channel */ WRITE_REGISTER_ULONG(0x48098010, 0x15); WRITE_REGISTER_ULONG(0x48098020, 0x1); WRITE_REGISTER_ULONG(0x48098028, 0x1); WRITE_REGISTER_ULONG(0x4809802c, 0x112fdc); /* Send the reset signal (R2 = 00h) to the NEC WVGA LCD Panel */ WRITE_REGISTER_ULONG(0x48098034, 0x1); WRITE_REGISTER_ULONG(0x48098038, 0x20100); WRITE_REGISTER_ULONG(0x48098034, 0x0); /* Turn on the functional and interface clocks in the DSS domain */ WRITE_REGISTER_ULONG(0x48004e00, 0x5); WRITE_REGISTER_ULONG(0x48004e10, 0x1); /* Reset the Display Controller (DISPC) */ WRITE_REGISTER_ULONG(0x48050410, 0x00000005); // DISPC_SYSCONFIG /* Set the frame buffer address */ WRITE_REGISTER_ULONG(0x48050480, 0x800A0000); // DISPC_GFX_BA0 /* Set resolution and RGB16 color mode */ WRITE_REGISTER_ULONG(0x4805048c, 0x01df031f); // DISPC_GFX_SIZE WRITE_REGISTER_ULONG(0x480504a0, 0x0000000d); // DISPC_GFX_ATTRIBUTES /* Set LCD timings (VSync and HSync), pixel clock, and LCD size */ WRITE_REGISTER_ULONG(0x4805046c, 0x00003000); // DISPC_POL_FREQ WRITE_REGISTER_ULONG(0x48050470, 0x00010004); // DISPC_DIVISOR WRITE_REGISTER_ULONG(0x48050464, 0x00300500); // DISPC_TIMING_H WRITE_REGISTER_ULONG(0x48050468, 0x00400300); // DISPC_TIMING_V WRITE_REGISTER_ULONG(0x4805047c, 0x01df031f); // DISPC_SIZE_LCD /* Turn the LCD on */ WRITE_REGISTER_ULONG(0x48050440, 0x00018309); // DISPC_CONTROL }
BOOLEAN HalHandleNMI( IN PKINTERRUPT Interrupt, IN PVOID ServiceContext ) /*++ Routine Description: This function is called when an EISA NMI occurs. It prints the appropriate status information and bugchecks. Arguments: Interrupt - Supplies a pointer to the interrupt object ServiceContext - Bug number to call bugcheck with. Return Value: Returns TRUE. --*/ { LEGO_SRV_MGMT SmRegister; UCHAR NmiControl, NmiStatus; BOOLEAN GotSerr, GotIochk, GotSmFan, GotSmTemp, GotHalt; NMIcount++; #if DBG if (NMIcount<5) { DbgPrint("II<NMI><"); } if (NMIcount % 100 == 0) { DbgPrint("II<NMI><%08x><", NMIcount); } #endif GotSerr = GotIochk = GotSmFan = GotSmTemp = GotHalt = FALSE; // // Set the Eisa NMI disable bit. We do this to mask further NMI // interrupts while we're servicing this one. // NmiControl = READ_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); ((PNMI_ENABLE)(&NmiControl))->NmiDisable = 1; WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, NmiControl); #ifdef DBG DbgPrint("HalHandleNMI: wrote 0x%x to NmiEnable\n", NmiControl); #endif NmiStatus = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus); if (NmiStatus & 0x80) { GotSerr = TRUE; #ifdef DBG DbgPrint("HalHandleNMI: Parity Check / Parity Error\n"); DbgPrint("HalHandleNMI: NMI Status = 0x%x\n", NmiStatus); #endif HalAcquireDisplayOwnership(NULL); HalDisplayString ("NMI: Parity Check / Parity Error\n"); KeBugCheck(NMI_HARDWARE_FAILURE); return (TRUE); } if (NmiStatus & 0x40) { GotIochk = TRUE; #ifdef DBG DbgPrint("HalHandleNMI: Channel Check / IOCHK\n"); DbgPrint("HalHandleNMI: NMI Status = 0x%x\n", NmiStatus); #endif HalAcquireDisplayOwnership(NULL); HalDisplayString ("NMI: Channel Check / IOCHK\n"); KeBugCheck(NMI_HARDWARE_FAILURE); return (TRUE); } // Read server management register // Events that can be reported as NMI are: // Enclosure temperature too high // CPU Fan failure // // For now, generate a bugcheck. // [wem] Future: perform secondary dispatch to give // driver shot at reporting problem. // SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); GotSmFan = SmRegister.CpuFanFailureNmi == 1; GotSmTemp = SmRegister.EnclTempFailureNmi == 1; if (GotSmFan || GotSmTemp) { #ifdef DBG DbgPrint("HalHandleNMI: Server management NMI\n"); DbgPrint("HalHandleNMI: NMI Status = 0x%x\n", NmiStatus); DbgPrint("HalHandleNMI: Server Management Status = 0x%x\n", SmRegister); #endif // // If secondary dispatch enabled, do it now. // #if 0 if (HalpLegoDispatchNmi && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SM_ERROR_VECTOR])( PCR->InterruptRoutine[SM_ERROR_VECTOR], TrapFrame) ) { return TRUE; } #endif // // Build uncorrectable error frame and // prepare for orderly shutdown // // The delayed shutdown depends on watchdog timer support // A power off cannot be directly done since KeBugChk() turns // off interrupts, so there's no way to get control back. // // WARNING: Pick a delay that allows a dump to complete. // LegoServerMgmtReportFatalError(SmRegister.All); LegoServerMgmtDelayedShutdown(8); // Issue reset in 8 seconds HalAcquireDisplayOwnership(NULL); HalDisplayString ("NMI: Hardware Failure -- "); HalDisplayString ((SmRegister.CpuFanFailureNmi==1) ? "CPU fan failed." : "Enclosure termperature too high."); HalDisplayString ("\nSystem Power Down will be attempted in 8 seconds...\n\n"); KeBugCheck(NMI_HARDWARE_FAILURE); return (TRUE); } // // Halt button was hit. // // [wem] Perform second-level dispatch here too? // if (!GotSerr && !GotIochk && !GotSmFan && !GotSmTemp) { // // If secondary dispatch enabled, do it now. // #if 0 if (HalpLegoDispatchHalt && ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[HALT_BUTTON_VECTOR])( PCR->InterruptRoutine[HALT_BUTTON_VECTOR], TrapFrame) ) { return TRUE; } #endif GotHalt = TRUE; HalDisplayString ("NMI: Halt button pressed.\n"); if (HalpHaltButtonBreak) { DbgBreakPoint(); } return (TRUE); } // // Clear and re-enable SERR# and IOCHK#, then re-enable NMI // #ifdef DBG DbgPrint("HalHandleNMI: Shouldn't get here!\n"); #endif if (GotSerr) { #ifdef DBG DbgPrint("HalHandleNMI: Resetting SERR#; NMI count = %d\n", NMIcount); #endif // // Reset SERR# (and disable it), then re-enable it. // WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x04); WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0); } if (GotIochk) { #ifdef DBG DbgPrint("HalHandleNMI: Resetting IOCHK#; NMI count = %d\n", NMIcount); #endif // // Reset IOCHK# (and disable it), then re-enable it. // WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x08); WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0); } if (GotSmFan || GotSmTemp) { // // Reset Server management condition. // // Interrupt must be cleared or the NMI will continue // to occur. // SmRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva ); if (GotSmFan) { SmRegister.CpuFanFailureNmi = 1; } else { SmRegister.EnclTempFailureNmi = 1; } WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoServerMgmtQva, SmRegister.All ); } // // Clear the Eisa NMI disable bit. This re-enables NMI interrupts, // now that we're done servicing this one. // NmiControl = READ_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); ((PNMI_ENABLE)(&NmiControl))->NmiDisable = 0; WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, NmiControl); #ifdef DBG DbgPrint("HalHandleNMI: wrote 0x%x to NmiEnable\n", NmiControl); #endif return(TRUE); }
VOID CardPrepareTransmit( IN PHTDSU_ADAPTER Adapter, IN USHORT CardLine, /* HTDSU_CMD_LINE1 or HTDSU_CMD_LINE2 */ IN USHORT BytesToSend ) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Functional Description: This routine will write the packet header information into the transmit buffer. This assumes that the controller has notified the driver that the transmit buffer is empty. Parameters: Adapter _ A pointer ot our adapter information structure. CardLine _ Specifies which line to use for the transmit (HTDSU_LINEx_ID). BytesToSend _ Number of bytes to transmit. Return Values: None ---------------------------------------------------------------------------*/ { DBG_FUNC("CardPrepareTransmit") DBG_ENTER(Adapter); ASSERT((CardLine==HTDSU_CMD_LINE1) || (CardLine==HTDSU_CMD_LINE2)); ASSERT(READ_REGISTER_USHORT(&Adapter->AdapterRam->TxDataEmpty)); ASSERT(BytesToSend > 0); /* // Tell the adapter how many bytes are to be sent, and which line to use. */ WRITE_REGISTER_USHORT( &Adapter->AdapterRam->TxBuffer.Address, (USHORT) (CardLine - HTDSU_CMD_LINE1) ); WRITE_REGISTER_USHORT( &Adapter->AdapterRam->TxBuffer.Length, BytesToSend ); /* // Mark the end of packet and end of packet list. */ WRITE_REGISTER_USHORT( &Adapter->AdapterRam->TxBuffer.Data[(BytesToSend+1)/sizeof(USHORT)], HTDSU_DATA_TERMINATOR ); WRITE_REGISTER_USHORT( &Adapter->AdapterRam->TxBuffer.Data[(BytesToSend+3)/sizeof(USHORT)], HTDSU_DATA_TERMINATOR ); DBG_LEAVE(Adapter); }
VOID HalpAcknowledgeClockInterrupt( VOID ) /*++ Routine Description: Acknowledge the clock interrupt from the interval timer. The interval timer for Lego comes from the Dallas real-time clock. Arguments: None. Return Value: None. --*/ { LEGO_WATCHDOG WdRegister; static LEGO_WATCHDOG WdRegisterDbg; static ULONG DbgWdCnt = 0; static ULONG WdNextService = 0; static BOOLEAN WdIntervalSet = FALSE; // // Make watchdog service interval a function of the timer period. // #if 1 static ULONG WdServiceIntervals[8] = {1, 1, 5, 15, 100, 600, 3000, 20000}; #else static ULONG WdServiceIntervals[8] = {1, 1, 1, 1, 1, 1, 1, 1}; #endif // // Acknowledge the clock interrupt by reading the control register C of // the Real Time Clock. // HalpReadClockRegister( RTC_CONTROL_REGISTERC ); // // If we are to service the Watchdog Timer, do it here // // Setting Phase to one will restart the timer... // [wem] this needs more work. For example, no need to touch it each clock tick!... // if (HalpLegoServiceWatchdog) { if (WdNextService==0) { // // read register to get service interval // WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva ); WdNextService = WdServiceIntervals[WdRegister.TimerOnePeriod]; #if DBG if (!WdIntervalSet) { DbgPrint(" <Watchdog:%04x> ",WdRegister.All); DbgPrint(" <WdInterval:%d> ",WdNextService); WdRegisterDbg.All = WdRegister.All; WdIntervalSet = TRUE; } #endif } WdNextService--; // // If service interval falls to zero, read register to service timer // if (WdNextService==0) { WdRegister.All = READ_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva ); #if DBG if (WdRegisterDbg.All != WdRegister.All) { WdRegisterDbg.All = WdRegister.All; DbgWdCnt = 0; } if (DbgWdCnt < 2) { DbgPrint(" <Watchdog:%04x> ",WdRegister.All); } if ((DbgWdCnt % 10000)==0) { DbgPrint(" <Watchdog:%04x> ",WdRegister.All); DbgWdCnt = 1; } DbgWdCnt++; #endif // // Reset the timer. This is done by writing 1 then 0 // to the Watchdog register's Phase bit // // If LegoDebugWatchdogIsr is true, let watchdog timer expire. // This will result in a watchdog interrupt or a system reset // depending on the watchdog mode. // if (!LegoDebugWatchdogIsr) { #if 0 if (HalpLegoWatchdogSingleMode) { WdRegister.Mode = WATCHDOG_MODE_1TIMER; } #endif WdRegister.Phase = 1; WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All); WdRegister.Phase = 0; WRITE_REGISTER_USHORT ((PUSHORT)HalpLegoWatchdogQva, WdRegister.All); } } } }
VOID HalDisableSystemInterrupt ( IN ULONG Vector, IN KIRQL Irql ) /*++ Routine Description: This routine disables the specified system interrupt. Arguments: Vector - Supplies the vector of the system interrupt that is disabled. Irql - Supplies the IRQL of the interrupting source. Return Value: None. --*/ { KIRQL OldIrql; // // Raise IRQL to the highest level and acquire device enable spinlock. // KeRaiseIrql(HIGH_LEVEL, &OldIrql); KiAcquireSpinLock(&HalpSystemInterruptLock); // // If the vector number is within the range of builtin devices, then // disable the builtin device interrupt. // if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) { HalpBuiltinInterruptEnable &= ~(1 << (Vector - DEVICE_VECTORS - 1)); #if defined(_R94A_) if ( READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ASIC3Revision.Long) == 0 ){ // // The bit assign of TYPHOON(in STORM chipset)'s I/O Device Interrupt // Enable register is zero origin. // // N.B. This obstruction is limiteded to beta-version of STORM chipset. // WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Fill, HalpBuiltinInterruptEnable); } else { WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable, HalpBuiltinInterruptEnable); } #else WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable, HalpBuiltinInterruptEnable); #endif } // // If the vector number is within the range of the EISA interrupts, then // disable the EISA interrrupt. // if (Vector >= EISA_VECTORS && Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR && Irql == EISA_DEVICE_LEVEL) { HalpDisableEisaInterrupt(Vector); } #if defined(_R94A_) // // If the vector number is within the range of the PCI interrupts, then // disable the PCI interrrupt. // if (Vector >= PCI_VECTORS && Vector <= PCI_VECTORS + R94A_PCI_SLOT && Irql == EISA_DEVICE_LEVEL) { HalpDisablePCIInterrupt(Vector); } #endif // // Release the device enable spin loc and lower IRQL to the previous level. // KiReleaseSpinLock(&HalpSystemInterruptLock); KeLowerIrql(OldIrql); return; }
VOID HalpResetS3Chip( VOID ) /*+++ This function resets/loads default values to the S3 Chip extended registers this code is borrowed/derived from the s3 miniport driver ---*/ { UCHAR byte; WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x4838); // unlock the S3 regs WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa539); // Unlock the SC regs WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen off byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA); WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte | 0x20)); // stop the sequencer WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0140); // Enable the enhanced 8514 registers WRITE_REGISTER_USHORT(S3_ADVFUNC_CNTL, 0x02); // reset to normal VGA operation WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0032); // Backward Compat 3 WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0035); // CRTC Lock WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x00); // async reset WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x01); // WRITE_REGISTER_UCHAR(VGA_FEAT_CNTRL, 0x00); // normal sync WRITE_REGISTER_UCHAR(VGA_MISC_READ, 0x00); // WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x8531); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x2033); // Backward Compat 2 WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0034); // Backward Compat 3 WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x853a); // S3 Misc 1 WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x5a3b); // Data Transfer Exec Pos WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x103c); // Interlace Retrace start WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x00); // start the sequencer WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x03); // WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa640); // VLB: 3Wait WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x1841); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0050); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0051); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff52); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0053); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x3854); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0055); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0056); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0057); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x8058); // ISA Latch ? (bit 3) WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x005c); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x005d); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x005e); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0760); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x8061); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa162); WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0043); // Extended Mode WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0045); // HW graphics Cursor Mode WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0046); // HW graphics Cursor Orig x WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff47); // HW graphics Cursor Orig x WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xfc48); // HW graphics Cursor Orig y WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff49); // HW graphics Cursor Orig y WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4a); // HW graphics Cursor Orig y WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4b); // HW graphics Cursor Orig y WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4c); // HW graphics Cursor Orig y WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4d); // HW graphics Cursor Orig y WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4e); // Dsp Start x pixel pos WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xdf4f); // Dsp Start y pixel pos WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0042); // select default clock WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x63); // Clock select /* // this should be done in the InitializeVGA code ... WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen on byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA); WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte & 0xdf)); // in the sequencer */ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0038); // lock s3 regs WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0039); // lock more s3 regs }