INT NTAPI LlbHwKbdRead(VOID) { /* Read current data on keyboard */ return READ_REGISTER_UCHAR(PL050_KMIDATA); }
UCHAR NTAPI ScsiPortReadRegisterUchar( IN PUCHAR Register) { return READ_REGISTER_UCHAR(Register); }
UCHAR NTAPI VideoPortReadRegisterUchar( PUCHAR Register) { return READ_REGISTER_UCHAR(Register); }
UCHAR ScsiPortReadRegisterUchar( IN PUCHAR Register ) /*++ Routine Description: Read from the specificed register address. Arguments: Register - Supplies a pointer to the register address. Return Value: Returns the value read from the specified register address. --*/ { return(READ_REGISTER_UCHAR(Register)); }
VOID HalpEnvironmentSetChecksum ( VOID ) /*++ Routine Description: This routine sets the NVRAM environment area checksum. N.B. The NVRAM must be mapped before this routine is called. Arguments: None. Return Value: None. --*/ { ULONG Checksum; PUCHAR Environment; ULONG Index; PNV_CONFIGURATION NvConfiguration; // // Compute the NVRAM environment area checksum. // NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE; Environment = &NvConfiguration->Environment[0]; Checksum = 0; for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) { Checksum += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]); } // // Write the NVRAM environment area checksum. // WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[0], (UCHAR)(Checksum & 0xFF)); WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[1], (UCHAR)((Checksum >> 8) & 0xFF)); WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[2], (UCHAR)((Checksum >> 16) & 0xFF)); WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[3], (UCHAR)(Checksum >> 24)); return; }
UCHAR HWREG<UCHAR>::Read( VOID ) { volatile UCHAR *addr = &m_Value; UCHAR v = READ_REGISTER_UCHAR((PUCHAR)addr); return v; }
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 KdPortPutByte ( IN UCHAR Output ) /*++ Routine Description: This routine puts a byte to the serial port used by the kernel debugger. N.B. It is assumed that the IRQL has been raised to the highest level, and necessary multiprocessor synchronization has been performed before this routine is called. Arguments: Output - Supplies the output data byte. Return Value: None. --*/ { UCHAR DataByte; // // Wait for transmit ready. // do { DataByte = READ_REGISTER_UCHAR(&SP_READ->LineStatus); } while (((PSP_LINE_STATUS)(&DataByte))->TransmitHoldingEmpty == 0); // // Wait for data set ready. // // do { // DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus); // } while (((PSP_MODEM_STATUS)(&DataByte))->DataSetReady == 0); // // Transmit data. // WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output); return; }
VOID NTAPI LlbHwKbdSend(IN ULONG Value) { ULONG Status; /* Wait for ready signal */ do { /* Read TX buffer state */ Status = READ_REGISTER_UCHAR(PL050_KMISTAT); } while (!(Status & KMISTAT_TXEMPTY)); /* Send value */ WRITE_REGISTER_UCHAR(PL050_KMIDATA, Value); }
UCHAR HalpReadClockRegister ( UCHAR Register ) /*++ Routine Description: This routine reads the specified realtime clock register. Arguments: Register - Supplies the number of the register whose value is read. Return Value: The value of the register is returned as the function value. --*/ { // // Insert the realtime clock register number, and write the value back // to the EISA NMI enable register. This selects the realtime clock register // that is read. Note this is a write only register and the EISA NMI // is always enabled. // // // TEMPTEMP Disable NMI's for now because this is causing machines in the // build lab to get NMI's during boot. // Register |= 0x80; WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, Register); // // Read the realtime clock register value. // return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase); }
VOID KdpReadIoSpaceExtended ( 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; 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; // // Zero the return data value. // a->DataValue = 0; // // Translate the bus address to the physical system address // or QVA. // if( !HalTranslateBusAddress( InterfaceType, BusNumber, IoAddress, &AddressSpace, &TranslatedAddress ) ){ m->ReturnStatus = STATUS_INVALID_PARAMETER; goto SendReadIoSpaceExtendedResponse; } // // 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 SendReadIoSpaceExtendedResponse; } // // 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: a->DataValue = READ_REGISTER_UCHAR( (PUCHAR)(ULONG_PTR) TranslatedAddress.QuadPart ); break; case 2: a->DataValue = READ_REGISTER_USHORT((PUSHORT)(ULONG_PTR) TranslatedAddress.QuadPart ); break; case 4: a->DataValue = READ_REGISTER_ULONG((PULONG)(ULONG_PTR) TranslatedAddress.QuadPart ); break; default: m->ReturnStatus = STATUS_INVALID_PARAMETER; } } else { // // I/O space on the bus // switch( DataSize ){ case 1: a->DataValue = READ_PORT_UCHAR( (PUCHAR)(ULONG_PTR) TranslatedAddress.QuadPart ); break; case 2: a->DataValue = READ_PORT_USHORT( (PUSHORT)(ULONG_PTR) TranslatedAddress.QuadPart ); break; case 4: a->DataValue = READ_PORT_ULONG( (PULONG)(ULONG_PTR) TranslatedAddress.QuadPart ); break; default: m->ReturnStatus = STATUS_INVALID_PARAMETER; } } SendReadIoSpaceExtendedResponse: KdpSendPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, NULL ); }
ULONG KdPortGetByte ( OUT PUCHAR Input ) /*++ Routine Description: This routine gets a byte from the serial port used by the kernel debugger. N.B. It is assumed that the IRQL has been raised to the highest level, and necessary multiprocessor synchronization has been performed before this routine is called. Arguments: Input - Supplies a pointer to a variable that receives the input data byte. Return Value: CP_GET_SUCCESS is returned if a byte is successfully read from the kernel debugger line. CP_GET_ERROR is returned if error encountered during reading. CP_GET_NODATA is returned if timeout. --*/ { UCHAR DataByte; ULONG TimeoutCount; // // Wait until data is available in the receive buffer. // TimeoutCount = TIMEOUT_COUNT; do { KeStallExecutionProcessor(1); DataByte = READ_REGISTER_UCHAR(&SP_READ->LineStatus); if (TimeoutCount-- == 0) { return CP_GET_NODATA; } } while (((PSP_LINE_STATUS)(&DataByte))->DataReady == 0); // // Read input byte and store in callers buffer. // *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer); // // Return function value as the not of the error indicators. // if (((PSP_LINE_STATUS)(&DataByte))->ParityError || ((PSP_LINE_STATUS)(&DataByte))->FramingError || ((PSP_LINE_STATUS)(&DataByte))->OverrunError || ((PSP_LINE_STATUS)(&DataByte))->BreakIndicator) { return CP_GET_ERROR; } else { return CP_GET_SUCCESS; } }
ARC_STATUS HalpFindEnvironmentVariable ( IN PCHAR Variable, OUT PULONG VariableIndex, OUT PULONG ValueIndex ) /*++ Routine Description: This routine performs a case insensitive search of the NVRAM environment area for the specified variable name. N.B. The NVRAM must be mapped before this routine is called. Arguments: Variable - Supplies a pointer to a zero terminated string containing an environment variable name. Return Value: ESUCCESS is returned if the specified variable name is located. Otherwise, ENOENT is returned. --*/ { PUCHAR Environment; ULONG Index; PUCHAR Name; // // If the variable name is null, then return no entry found. // if (*Variable == 0) { return ENOENT; } // // Search the environment section of the NVRAM for a variable name match. // Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0]; Index = 0; do { // // Set name to the beginning of the variable name and record the // current index value. // Name = Variable; *VariableIndex = Index; // // Search until the end of the current environment variable, the // end of the specified variable name, or the end of the NVRAM is // reached. // while ((Index < LENGTH_OF_ENVIRONMENT) && (READ_REGISTER_UCHAR(&Environment[Index]) != 0) && (*Name != 0)) { if (READ_REGISTER_UCHAR(&Environment[Index]) != UpCase(*Name)) { break; } Name += 1; Index += 1; } // // Check for a match which is signified by the end of the variable // name and the equal separator in the current environment variable. // if ((*Name == 0) && (READ_REGISTER_UCHAR(&Environment[Index]) == '=')) { *ValueIndex = Index + 1; return ESUCCESS; } // // Advance to the start of the next variable. // while ((Index < LENGTH_OF_ENVIRONMENT) && (READ_REGISTER_UCHAR(&Environment[Index]) != 0)) { Index += 1; } Index += 1; } while (Index < LENGTH_OF_ENVIRONMENT); return ENOENT; }
ULONG HalpGetByte ( IN PCHAR Input, IN BOOLEAN Wait ) /*++ Routine Description: This routine gets a byte from the serial port used by the kernel debugger. Arguments: Input - Supplies a pointer to a variable that receives the input data byte. Wait - Supplies a boolean value that detemines whether a timeout is applied to the input operation. Return Value: CP_GET_SUCCESS is returned if a byte is successfully read from the kernel debugger line. CP_GET_ERROR is returned if an error is encountered during reading. CP_GET_NODATA is returned if timeout occurs. --*/ { SP_LINE_STATUS LsrByte; UCHAR DataByte; ULONG TimeoutCount; // // Attempt to read a byte from the debugger port until a byte is // available or until a timeout occurs. // TimeoutCount = Wait ? TIMEOUT_COUNT : 1; do { TimeoutCount -= 1; // // Wait until data is available in the receive buffer. // KeStallExecutionProcessor(1); LsrByte = KdReadLsr(TRUE); if (LsrByte.DataReady == 0) { continue; } // // Read input byte and store in callers buffer. // *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer); // // If using modem controls, then skip any incoming data while // ReceiveData not set. // if (KdUseModemControl) { DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus); if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) { continue; } } // // Return function value as the not of the error indicators. // if (LsrByte.ParityError || LsrByte.FramingError || LsrByte.OverrunError || LsrByte.BreakIndicator) { return CP_GET_ERROR; } return CP_GET_SUCCESS; } while(TimeoutCount != 0); return CP_GET_NODATA; }
VOID KdPortPutByte ( IN UCHAR Output ) /*++ Routine Description: This routine puts a byte to the serial port used by the kernel debugger. N.B. It is assumed that the IRQL has been raised to the highest level, and necessary multiprocessor synchronization has been performed before this routine is called. Arguments: Output - Supplies the output data byte. Return Value: None. --*/ { UCHAR DataByte; PSP_MODEM_STATUS LsrByte; if (KdUseModemControl) { // // Modem control, make sure DSR, CTS and CD are all set before // sending any data. // for (; ;) { DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus); if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend && ((PSP_MODEM_STATUS)&DataByte)->DataSetReady && ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) { break; } KdReadLsr(FALSE); } } // // Wait for transmit ready. // while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 ); // // Wait for data set ready. // // do { // LsrByte = (PSP_MODEM_STATUS) READ_REGISTER_UCHAR(&SP_READ->ModemStatus); // } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0); // // Transmit data. // WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output); return; }
BOOLEAN HalpHandleExternalInterrupt( IN PKINTERRUPT Interrupt, IN PVOID ServiceContext, IN PVOID TrapFrame ) /*++ Routine Description: This routine is entered as the result of an interrupt being generated via the vector that is connected to an interrupt object that describes the SIO device interrupts. Its function is to call the second level interrupt dispatch routine and acknowledge the interrupt at the SIO controller. N.B. This routine is entered and left with external interrupts disabled. Arguments: Interrupt - Supplies a pointer to the interrupt object. ServiceContext - Supplies a pointer to the SIO interrupt acknowledge register. None. Return Value: Returns the value returned from the second level routine. --*/ { PSECONDARY_DISPATCH SioHandler; PKINTERRUPT SioInterrupt; USHORT interruptVector; BOOLEAN returnValue; UCHAR OldIrql; USHORT Isr; UCHAR Irql; // // Read the interrupt vector. // interruptVector = READ_REGISTER_UCHAR(HalpInterruptBase); // // check for nmi interrupt before we raise irql since we would raise to a // bogus level // if (interruptVector == 0xFF) { HalpHandleMachineCheck(NULL, NULL); } // // check for spurious interrupt // if (interruptVector == SPURIOUS_VECTOR) { WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0, 0x0B); Isr = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0); if (!(Isr & 0x80)) { // // Spurious interrupt // #if DBG //DbgPrint("A spurious interrupt occurred. \n"); HalpSpuriousInterruptCount++; #endif return(0); } } if (interruptVector > HIGHEST_8259_VECTOR) { #if DBG DbgPrint("A bogus interrupt (0x%02x) occurred. \n", interruptVector); HalpBogusInterruptCount++; #endif return (0); } // // Translate vector to IRQL and raise IRQL // Irql = HalpTranslateVectorToIrql(interruptVector); KeRaiseIrql( Irql, &OldIrql); // // Dispatch to the secondary interrupt service routine. // SioHandler = (PSECONDARY_DISPATCH) PCR->InterruptRoutine[DEVICE_VECTORS + interruptVector]; SioInterrupt = CONTAINING_RECORD(SioHandler, KINTERRUPT, DispatchCode[0]); returnValue = SioHandler(SioInterrupt, SioInterrupt->ServiceContext, TrapFrame ); // // Dismiss the interrupt in the SIO interrupt controllers. // // // If this is a cascaded interrupt then the interrupt must be dismissed in // both controllers. // if (interruptVector & 0x08) { WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0, NONSPECIFIC_END_OF_INTERRUPT ); } WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0, NONSPECIFIC_END_OF_INTERRUPT ); // // Lower IRQL but disable external interrupts. // Return to caller with interrupts disabled. // HalpResetIrqlAfterInterrupt(OldIrql); return(returnValue); }
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. --*/ { UCHAR StatusByte; UCHAR EisaPort; ULONG port; ULONG AddressSpace = 1; // 1 = I/O address space BOOLEAN Status; PHYSICAL_ADDRESS BusAddress; PHYSICAL_ADDRESS TranslatedAddress; UCHAR Datum; NMIcount++; // // Set the Eisa NMI disable bit. We do this to mask further NMI // interrupts while we're servicing this one. // Datum = READ_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); ((PNMI_ENABLE)(&Datum))->NmiDisable = 1; WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, Datum); #ifdef HALDBG DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", Datum); #endif StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus); if (StatusByte & 0x80) { #ifdef HALDBG DbgPrint("HalHandleNMI: Parity Check / Parity Error\n"); DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte); #else // // jwlfix - For the present, we're commenting out an NMI parity // error bugcheck, until investigation into its causes // yields a better solution. // // HalDisplayString ("NMI: Parity Check / Parity Error\n"); // KeBugCheck(NMI_HARDWARE_FAILURE); // return (TRUE); #endif } Datum = READ_REGISTER_UCHAR((PUCHAR)HalpServerControlQva ); if (((PMIKASA_SRV)(&Datum))->HaltIncoming == 0 || ((PMIKASA_SRV)(&Datum))->TempFail == 1 || ((PMIKASA_SRV)(&Datum))->Fan1Fault == 0 || ((PMIKASA_SRV)(&Datum))->Fan2Fault == 0) { #ifdef HALDBG DbgPrint("HalHandleNMI: Server management NMI\n"); DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte); DbgPrint("HalHandleNMI: Server Management Byte = 0x%x\r\n", Datum); #else // // jwlfix - All the above conditions are for handling server // management features. Implementing more than simple // dismissal waits upon definition of desired behavior // by platform designers or Microsoft Windows NT // requirements for server behavior. #endif } if (StatusByte & 0x40) { #ifdef HALDBG DbgPrint("HalHandleNMI: Channel Check / IOCHK\n"); DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte); #else HalDisplayString ("NMI: Channel Check / IOCHK\n"); KeBugCheck(NMI_HARDWARE_FAILURE); return (TRUE); #endif } #if 0 // jwlfix - This code can be added in later, as we have need // for it. It's good to have it here, for when it // might be of use. // // This is an Eisa machine, check for extnded nmi information... // StatusByte = READ_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl); if (StatusByte & 0x80) { HalDisplayString ("NMI: Fail-safe timer\n"); } if (StatusByte & 0x40) { HalDisplayString ("NMI: Bus Timeout\n"); } if (StatusByte & 0x20) { HalDisplayString ("NMI: Software NMI generated\n"); } // // Look for any Eisa expansion board. See if it asserted NMI. // // jwlfix - The following doesn't work, at this moment; it's // likey the 12-bit shift, which should be a 5-bit // shift on Mikasa. // BusAddress.HighPart = 0; for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) { BusAddress.LowPart = (EisaPort << 12) + 0xC80; Status = HalTranslateBusAddress(Eisa, // InterfaceType 0, // BusNumber BusAddress, &AddressSpace, // 1=I/O address space &TranslatedAddress); // QVA if (Status == FALSE) { UCHAR pbuf[80]; sprintf(pbuf, "Unable to translate bus address %x for EISA slot %d\n", BusAddress.LowPart, EisaPort); HalDisplayString(pbuf); KeBugCheck(NMI_HARDWARE_FAILURE); } port = TranslatedAddress.LowPart; WRITE_PORT_UCHAR ((PUCHAR) port, 0xff); StatusByte = READ_PORT_UCHAR ((PUCHAR) port); if ((StatusByte & 0x80) == 0) { // // Found valid Eisa board, Check to see if its // IOCHKERR is asserted. // StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4); if (StatusByte & 0x2) { EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort; HalDisplayString (EisaNMIMsg); KeBugCheck(NMI_HARDWARE_FAILURE); } } } #ifdef HALDBG // Reset extended NMI interrupts (for debugging purposes only). WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x00); WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x02); #endif #endif #ifdef HALDBG DbgPrint("HalHandleNMI: Resetting PERR#; NMI count = %d\r\n", NMIcount); #endif // // Reset PERR# and disable it. // WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x04); // // now enable it again. // WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0); // // Clear the Eisa NMI disable bit. This re-enables NMI interrupts, // now that we're done servicing this one. // Datum = READ_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); ((PNMI_ENABLE)(&Datum))->NmiDisable = 0; WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, Datum); #ifdef HALDBG DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", Datum); #endif return(TRUE); }
ULONG x86BiosReadIoSpace ( IN XM_OPERATION_DATATYPE DataType, IN USHORT PortNumber ) /*++ Routine Description: This function reads from emulated I/O space. Arguments: DataType - Supplies the datatype for the read operation. PortNumber - Supplies the port number in I/O space to read from. Return Value: The value read from I/O space is returned as the function value. N.B. If an aligned operation is specified, then the individual bytes are read from the specified port one at a time and assembled into the specified datatype. --*/ { ULONG Result; ULONG PciBusNumber; PCI_SLOT_NUMBER SlotNumber; union { PUCHAR Byte; PUSHORT Word; PULONG Long; } u; // // Compute port address and read port. // // // If PortNumber is in ISA Motherboard space, then overide the base address of // the IO space with ISA space, otherwise, use the base address passed in on // initialization. // if (PortNumber < 0x1000 && ((PortNumber & 0x3ff) < 0x100)) { u.Long = (PULONG)((ULONG)HalpEisaControlBase[0] + PortNumber); } else { u.Long = (PULONG)(x86BiosIoSpace + PortNumber); } if (DataType == BYTE_DATA) { Result = READ_REGISTER_UCHAR(u.Byte); } else if (DataType == LONG_DATA) { // // If PortNumber is attempting to access the PCI config registers defined for X86 systems, // intercept them, and make the appropriate HAL call to get the PCI confoguration data. // if (PortNumber == 0xcf8) { Result = HalpPciConfigAddress; } else if (PortNumber == 0xcfc && (HalpPciConfigAddress & 0x80000000)) { PciBusNumber = (HalpPciConfigAddress >> 16) & 0xff; SlotNumber.u.AsULONG = 0; SlotNumber.u.bits.DeviceNumber = (HalpPciConfigAddress >> 11) & 0x1f; SlotNumber.u.bits.FunctionNumber = (HalpPciConfigAddress >> 8) & 0x07; HalGetBusDataByOffset (PCIConfiguration, PciBusNumber, SlotNumber.u.AsULONG, &Result, HalpPciConfigAddress & 0xfc, 4 ); } else { if (((ULONG)u.Long & 0x3) != 0) {
BOOLEAN NTAPI LlbHwKbdReady(VOID) { return READ_REGISTER_UCHAR(PL050_KMISTAT) & KMISTAT_RXFULL; }
ARC_STATUS HalSetEnvironmentVariable ( IN PCHAR Variable, IN PCHAR Value ) /*++ Routine Description: This function creates an environment variable with the specified value. Arguments: Variable - Supplies a pointer to an environment variable name. Value - Supplies a pointer to the environment variable value. Return Value: ESUCCESS is returned if the environment variable is created. Otherwise, ENOMEM is returned. --*/ { UCHAR Character; PUCHAR Environment; KIRQL OldIrql; ENTRYLO SavedPte[2]; ARC_STATUS Status; ULONG TopIndex; ULONG VariableIndex; ULONG VariableLength; ULONG ValueEnd; ULONG ValueIndex; ULONG ValueLength; #if DBG DbgPrint("NVRAM 1S\n"); #endif // // Map the NVRAM into the address space of the current process. // OldIrql = HalpMapNvram(&SavedPte[0]); Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0]; // // If the checksum does not match, then set status to an I/O error. // if (HalpEnvironmentCheckChecksum() != ESUCCESS) { Status = EIO; goto Unmap; } // // Determine the top of the environment area by scanning backwards until // the a non-null character is found or the beginning of the environment // area is reached. // for (TopIndex = (LENGTH_OF_ENVIRONMENT - 1); TopIndex > 0; TopIndex -= 1) { if (READ_REGISTER_UCHAR(&Environment[TopIndex]) != '\0') { break; } } // // If the environment area contains any data, then adjust the top index // to the first free byte. // if (TopIndex != 0) { TopIndex += 2; } // // Compute the length of the variable name and the variable value. // VariableLength = strlen(Variable) + 1; ValueLength = strlen(Value) + 1; // // Check to determine if the specified variable is currently defined. // if (HalpFindEnvironmentVariable(Variable, &VariableIndex, &ValueIndex) == ESUCCESS) { // // The specified variable is currently defined. Determine the end // of the variable value by scanning forward to the zero termination // byte. // ValueEnd = ValueIndex; while (READ_REGISTER_UCHAR(&Environment[ValueEnd]) != '\0') { ValueEnd += 1; } ValueEnd += 1; // // If there is enough free space for the new variable value, then // remove the current variable name and value from the environment // area, insert the new variable value at the end of the environment // if it is not null, and set the status to success. Otherwise, set // the status to no space available. // if ((ValueEnd - ValueIndex + LENGTH_OF_ENVIRONMENT - TopIndex) >= ValueLength) { while (ValueEnd != TopIndex) { Character = READ_REGISTER_UCHAR(&Environment[ValueEnd]); WRITE_REGISTER_UCHAR(&Environment[VariableIndex], Character); ValueEnd += 1; VariableIndex += 1; } ValueIndex = VariableIndex; while (ValueIndex != TopIndex) { WRITE_REGISTER_UCHAR(&Environment[ValueIndex], '\0'); ValueIndex += 1; } // // If the new variable value is not null, then copy the variable // name and the variable value into the enviroment area. // if (*Value != '\0') { // // copy the variable name to the environment area. // do { WRITE_REGISTER_UCHAR(&Environment[VariableIndex], UpCase(*Variable)); VariableIndex += 1; Variable += 1; } while (*Variable != '\0'); // // Insert separator character and copy variable value to the // environment area. // WRITE_REGISTER_UCHAR(&Environment[VariableIndex], '='); VariableIndex += 1; do { WRITE_REGISTER_UCHAR(&Environment[VariableIndex], *Value); VariableIndex += 1; Value += 1; } while (*Value != '\0'); } Status = ESUCCESS; } else { Status = ENOSPC; } } else { // // The specified variable does not currently have a value. If the // specified variable is null or has no value, then set the status // to success. Otherwise, if the free area is not large enough to // hold the new variable name and its value, then set the status to // no space available. Otherwise, insert the variable name and value // at the end of the environment area and set the status to success. // if ((*Variable == '\0') || (*Value == '\0')) { Status = ESUCCESS; } else if ((LENGTH_OF_ENVIRONMENT - TopIndex) < (VariableLength + ValueLength)) { Status = ENOSPC; } else { // // copy the variable name to the environment area. // do { WRITE_REGISTER_UCHAR(&Environment[TopIndex], UpCase(*Variable)); TopIndex += 1; Variable += 1; } while (*Variable != '\0'); // // Insert separator character and copy variable value to the // environment area. // WRITE_REGISTER_UCHAR(&Environment[TopIndex], '='); TopIndex += 1; do { WRITE_REGISTER_UCHAR(&Environment[TopIndex], *Value); TopIndex += 1; Value += 1; } while (*Value != '\0'); Status = ESUCCESS; } } // // Compute the new checksum and write to the environment area. // HalpEnvironmentSetChecksum(); // // Unmap the NVRAM from the address space of the current process. // Unmap: HalpUnmapNvram(&SavedPte[0], OldIrql); #if DBG DbgPrint("NVRAM 1E\n"); #endif return Status; }
ARC_STATUS HalGetEnvironmentVariable ( IN PCHAR Variable, IN USHORT Length, OUT PCHAR Buffer ) /*++ Routine Description: This function locates an environment variable and returns its value. Arguments: Variable - Supplies a pointer to a zero terminated environment variable name. Length - Supplies the length of the value buffer in bytes. Buffer - Supplies a pointer to a buffer that receives the variable value. Return Value: ESUCCESS is returned if the enviroment variable is located. Otherwise, ENOENT is returned. --*/ { PUCHAR Environment; ULONG Index; KIRQL OldIrql; ENTRYLO SavedPte[2]; ARC_STATUS Status; ULONG ValueIndex; ULONG VariableIndex; #if defined(DBG1) DbgPrint("NVRAM 0S\n"); #endif // // Map the NVRAM into the address space of the current process. // OldIrql = HalpMapNvram(&SavedPte[0]); // // If the checksum does not match or the specified variable cannot // be located, then set the status to no entry found. Otherwise, copy // the respective variable value to the specified output buffer. // Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0]; if ((HalpEnvironmentCheckChecksum() != ESUCCESS) || (HalpFindEnvironmentVariable(Variable, &VariableIndex, &ValueIndex) != ESUCCESS)) { Status = ENOENT; } else { // // Copy the specified value to the output buffer. // for (Index = 0; Index < Length; Index += 1) { *Buffer = READ_REGISTER_UCHAR(&Environment[ValueIndex]); if (*Buffer == 0) { break; } Buffer += 1; ValueIndex += 1; } // // If the length terminated the loop, then return not enough memory. // Otherwise, return success. // if (Index == Length) { Status = ENOMEM; } else { Status = ESUCCESS; } } // // Unmap the NVRAM from the address space of the current process and // return the function status. // HalpUnmapNvram(&SavedPte[0], OldIrql); #if defined(DBG1) DbgPrint("NVRAM 0E\n"); #endif return Status; }
BOOLEAN HalMakeBeep( IN ULONG Frequency ) /*++ Routine Description: This function sets the frequency of the speaker, causing it to sound a tone. The tone will sound until the speaker is explicitly turned off, so the driver is responsible for controlling the duration of the tone. Arguments: Frequency - Supplies the frequency of the desired tone. A frequency of 0 means the speaker should be shut off. Return Value: TRUE - Operation was successful (frequency within range or zero). FALSE - Operation was unsuccessful (frequency was out of range). Current tone (if any) is unchanged. --*/ { KIRQL OldIrql; NMI_STATUS NmiStatus; PEISA_CONTROL controlBase = HalpEisaControlBase; TIMER_CONTROL timerControl; ULONG newCount; BOOLEAN Result; if ( HalpPmpRevision >= 3 ) { // // For PMP V3, we are NOT using speaker timer in ESC for speaker tone. // Need to add code to generate via sound card. // Result = TRUE; return Result; } // // Raise IRQL to dispatch level and acquire the beep spin lock. // KeAcquireSpinLock(&HalpBeepLock, &OldIrql); // // Stop the speaker. // *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus); NmiStatus.SpeakerGate = 0; NmiStatus.SpeakerData = 0; WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus)); // // If the specified frequency is zero, then the speaker is to be stopped. // if (Frequency == 0) { Result = TRUE; } else { // // If the new count has a magnitude less than 65,536 (0x10000), then // set the speaker time to the correct mode. Otherwise, return a value // of FALSE sinc ethe frequency is out of range. // newCount = TIMER_CLOCK_IN / Frequency; if (newCount >= 0x10000) { Result = FALSE; } else { // // Set the speaker timer to the correct mode. // timerControl.BcdMode = 0; timerControl.Mode = TM_SQUARE_WAVE; timerControl.SelectByte = SB_LSB_THEN_MSB; timerControl.SelectCounter = SELECT_COUNTER_2; WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl)); // // Set the speaker timer to the correct mode. // WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff)); WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8)); // // Start the speaker. // NmiStatus.SpeakerGate = 1; NmiStatus.SpeakerData = 1; WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus)); Result = TRUE; } } // // Release the beep spin lock and lower IRQL to its previous value. // KeReleaseSpinLock(&HalpBeepLock, OldIrql); return Result; }
BOOLEAN HalpCreateSioStructures ( VOID ) /*++ Routine Description: This routine initializes the structures necessary for SIO operations and connects the intermediate interrupt dispatcher. Arguments: None. Return Value: If the second level interrupt dispatcher is connected, then a value of TRUE is returned. Otherwise, a value of FALSE is returned. --*/ { UCHAR DataByte; KIRQL oldIrql; // // Initialize the Machine Check interrupt handler // if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt, HalpHandleMachineCheck, NULL, NULL, MACHINE_CHECK_VECTOR, MACHINE_CHECK_LEVEL, MACHINE_CHECK_LEVEL, Latched, FALSE, 0, FALSE, InternalUsage, MACHINE_CHECK_VECTOR ) == FALSE) { KeBugCheck(HAL_INITIALIZATION_FAILED); } // // Enable NMI IOCHK# and PCI SERR# // DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus); WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus, DataByte & ~DISABLE_IOCHK_NMI & ~DISABLE_PCI_SERR_NMI); // // Clear the SIO NMI disable bit. This bit is the high order of the // NMI enable register. // DataByte = 0; WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpIoControlBase)->NmiEnable, DataByte ); // // Connect the external interrupt handler // PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] = (PKINTERRUPT_ROUTINE) HalpHandleExternalInterrupt; // // register the interrupt vector // HalpRegisterVector(InternalUsage, EXTERNAL_INTERRUPT_VECTOR, EXTERNAL_INTERRUPT_VECTOR, HIGH_LEVEL); // Connect directly to the decrementer handler. This is done // directly rather than thru HalpEnableInterruptHandler due to // special handling required because the handler calls KdPollBreakIn(). // PCR->InterruptRoutine[DECREMENT_VECTOR] = (PKINTERRUPT_ROUTINE) HalpHandleDecrementerInterrupt; // // Initialize and connect the Timer 1 interrupt (IRQ0) // if (HalpEnableInterruptHandler( &HalpProfileInterrupt, (PKSERVICE_ROUTINE) HalpHandleProfileInterrupt, (PVOID) NULL, (PKSPIN_LOCK)NULL, PROFILE_VECTOR, PROFILE_LEVEL, PROFILE_LEVEL, Latched, TRUE, 0, FALSE, DeviceUsage, PROFILE_VECTOR ) == FALSE) { KeBugCheck(HAL_INITIALIZATION_FAILED); } // // Disable Timer 1; only used by profiling // HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL); // // Set default profile rate // HalSetProfileInterval(5000); // // Raise the IRQL while the SIO interrupt controller is initialized. // KeRaiseIrql(CLOCK2_LEVEL, &oldIrql); // // Initialize any planar registers // HalpInitPlanar(); // // Enable the clock interrupt // HalpUpdateDecrementer(1000); // Get those decrementer ticks going // // Set ISA bus interrupt affinity. // HalpIsaBusAffinity = PCR->SetMember; // // Restore IRQL level. // KeLowerIrql(oldIrql); // // DMA command - set assert level // DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus); WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus, DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW); // // Initialize the DMA mode registers to a default value. // Disable all of the DMA channels except channel 4 which is that // cascade of channels 0-3. // WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask, 0x0F ); WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask, 0x0E ); return(TRUE); }
} else if (PortNumber == 0xcfc && (HalpPciConfigAddress & 0x80000000)) { PciBusNumber = (HalpPciConfigAddress >> 16) & 0xff; SlotNumber.u.AsULONG = 0; SlotNumber.u.bits.DeviceNumber = (HalpPciConfigAddress >> 11) & 0x1f; SlotNumber.u.bits.FunctionNumber = (HalpPciConfigAddress >> 8) & 0x07; HalGetBusDataByOffset (PCIConfiguration, PciBusNumber, SlotNumber.u.AsULONG, &Result, HalpPciConfigAddress & 0xfc, 4 ); } else { if (((ULONG)u.Long & 0x3) != 0) { Result = (READ_REGISTER_UCHAR(u.Byte + 0)) | (READ_REGISTER_UCHAR(u.Byte + 1) << 8) | (READ_REGISTER_UCHAR(u.Byte + 2) << 16) | (READ_REGISTER_UCHAR(u.Byte + 3) << 24); } else { Result = READ_REGISTER_ULONG(u.Long); } } } else { if (((ULONG)u.Word & 0x1) != 0) { Result = (READ_REGISTER_UCHAR(u.Byte + 0)) | (READ_REGISTER_UCHAR(u.Byte + 1) << 8); } else {
ARC_STATUS HalGetEnvironmentVariable ( IN PCHAR Variable, IN USHORT Length, OUT PCHAR Buffer ) /*++ Routine Description: This function locates an environment variable and returns its value. Arguments: Variable - Supplies a pointer to a zero terminated environment variable name. Length - Supplies the length of the value buffer in bytes. Buffer - Supplies a pointer to a buffer that receives the variable value. Return Value: ESUCCESS is returned if the enviroment variable is located. Otherwise, ENOENT is returned. NOTE: This implementation returns the error code ENOMEM if the output buffer is too small. --*/ { PUCHAR Environment_var; ULONG Index; ARC_STATUS Status; // // retrieve the variable // Environment_var = (PUCHAR)ArcGetEnvironmentVariable(Variable); if (Environment_var == (PUCHAR)NULL) { Status = ENOENT; } else { // // Copy the specified value to the output buffer. // for (Index = 0; Index < Length; Index += 1) { *Buffer = READ_REGISTER_UCHAR(Environment_var); if (*Buffer == 0) { break; } Buffer += 1; Environment_var += 1; } // // If the length terminated the loop, then return not enough memory. // Otherwise, return success. // if (Index == Length) { Status = ENOMEM; } else { Status = ESUCCESS; } } return Status; }
VOID DrainTransmit( PDIGI_CONTROLLER_EXTENSION ControllerExt, PDIGI_DEVICE_EXTENSION DeviceExt, PIRP Irp ) /*++ Routine Description: We do the necessary checks to determine if the controller has transmitted all the data it has been given. The check basically is: if( CIN == COUT TIN == TOUT TBusy == 0 ) transmit buffer is empty. NOTE: Care should be taken when using this function, and at what dispatch level it is being called from. I don't do any synch'ing with the WriteQueue in the DeviceObject. So it is potentially possible that data could keep getting put on the controller while the function is waiting for it to drain. Arguments: ControllerExt - a pointer to this devices controllers extension. DeviceObject - a pointer to this devices object. Irp - Pointer to the current Irp request whose context this function is being called. This allows us to determine if the Irp has been cancelled. Return Value: --*/ { PFEP_CHANNEL_STRUCTURE ChInfo; PCOMMAND_STRUCT CommandQ; COMMAND_STRUCT CmdStruct; UCHAR TBusy; ULONG count; USHORT OrgTout, Tin, Tout; TIME DelayInterval; ChInfo = (PFEP_CHANNEL_STRUCTURE)(ControllerExt->VirtualAddress + DeviceExt->ChannelInfo.Offset); EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window ); Tin = READ_REGISTER_USHORT( &ChInfo->tin ); Tout = READ_REGISTER_USHORT( &ChInfo->tout ); TBusy = READ_REGISTER_UCHAR( &ChInfo->tbusy ); DisableWindow( ControllerExt ); OrgTout = Tout; // // Get the command queue info // CommandQ = ((PCOMMAND_STRUCT)(ControllerExt->VirtualAddress + FEP_CIN)); EnableWindow( ControllerExt, ControllerExt->Global.Window ); READ_REGISTER_BUFFER_UCHAR( (PUCHAR)CommandQ, (PUCHAR)&CmdStruct, sizeof(CmdStruct) ); DisableWindow( ControllerExt ); // // Delay for 10 milliseconds // #if rmm < 807 DelayInterval = RtlConvertLongToLargeInteger( -10 * 10000 ); #else DelayInterval.QuadPart = -10 * 10000; #endif count = 0; while( ((Tin != Tout) || (TBusy) || (CmdStruct.cmHead != CmdStruct.cmTail)) && !Irp->Cancel ) { ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL ); // not DPC, or KeDelay won't ever return KeDelayExecutionThread( KernelMode, FALSE, &DelayInterval ); EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window ); Tin = READ_REGISTER_USHORT( &ChInfo->tin ); Tout = READ_REGISTER_USHORT( &ChInfo->tout ); TBusy = READ_REGISTER_UCHAR( &ChInfo->tbusy ); DisableWindow( ControllerExt ); EnableWindow( ControllerExt, ControllerExt->Global.Window ); READ_REGISTER_BUFFER_UCHAR( (PUCHAR)CommandQ, (PUCHAR)&CmdStruct, sizeof(CmdStruct) ); DisableWindow( ControllerExt ); if( Tout != OrgTout ) { count = 0; OrgTout = Tout; } if( count++ > 2500 ) { // // We have waited for 25 seconds and haven't seen the transmit // buffer change. Assume we are in a deadlock flow control state // and exit! // // // We go ahead and flush the transmit queue because a close // may be following soon, and we don't want it to have to // wait again. Basically, it had its chance to drain. // FlushTransmitBuffer( ControllerExt, DeviceExt ); break; } } } // end DrainTransmit
SP_LINE_STATUS KdReadLsr ( IN BOOLEAN WaitReason ) /*++ Routine Description: Returns current line status. If status which is being waited for is ready, then the function checks the current modem status and causes a possible display update of the current statuses. Arguments: WaitReason - Supplies a boolean value that determines whether the line status is required for a receive or transmit. Return Value: The current line status is returned as the function value. --*/ { static UCHAR RingFlag = 0; UCHAR DataLsr, DataMsr; // // Get the line status for a recevie or a transmit. // DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus); if (WaitReason) { // // Get line status for receive data. // if (((PSP_LINE_STATUS)&DataLsr)->DataReady) { return *((PSP_LINE_STATUS)&DataLsr); } } else { // // Get line status for transmit empty. // if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) { return *((PSP_LINE_STATUS)&DataLsr); } } DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus); RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2; if (RingFlag == 3) { // // The ring indicate line has toggled, use modem control from // now on. // KdUseModemControl = TRUE; } return *((PSP_LINE_STATUS) &DataLsr); }
USHORT NBytesInRecvBuffer( PDIGI_CONTROLLER_EXTENSION ControllerExt, PDIGI_DEVICE_EXTENSION DeviceExt ) /*++ Routine Description: Determine the number of actual bytes in the receive buffer. This routine takes into account DOSMODE on the controller. Arguments: ControllerExt - pointer to the controller extension information assosicated with DeviceExt. DeviceExt - pointer to the device specific information. Return Value: Number of bytes in the receive buffer. --*/ { PUCHAR ControllerBuffer; PFEP_CHANNEL_STRUCTURE ChInfo; USHORT AmountInQueue; USHORT Rin, Rout, Rmax; USHORT DosMode; UCHAR ReceivedByte, SecondReceivedByte; ControllerBuffer = ControllerExt->VirtualAddress + DeviceExt->RxSeg.Offset; ChInfo = (PFEP_CHANNEL_STRUCTURE)(ControllerExt->VirtualAddress + DeviceExt->ChannelInfo.Offset); EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window ); Rout = READ_REGISTER_USHORT( &ChInfo->rout ); Rin = READ_REGISTER_USHORT( &ChInfo->rin ); Rmax = READ_REGISTER_USHORT( &ChInfo->rmax ); DosMode = READ_REGISTER_USHORT( &ChInfo->iflag ); DisableWindow( ControllerExt ); DosMode &= IFLAG_DOSMODE; if( !DosMode ) { AmountInQueue = Rin - Rout; if( (SHORT)AmountInQueue < 0) AmountInQueue += (Rmax + 1); return( AmountInQueue ); } AmountInQueue = 0; EnableWindow( ControllerExt, DeviceExt->RxSeg.Window ); DigiDump( DIGIIOCTL, (" NRecvRoutine: Rin = 0x%x, Rout = 0x%x\n", Rin, Rout) ); while( Rout != Rin ) { ReceivedByte = READ_REGISTER_UCHAR( (ControllerBuffer + Rout) ); Rout++; Rout &= Rmax; AmountInQueue++; DigiDump( DIGIIOCTL, (" NRecvByte = 0x%x, Rout = 0x%x\n", ReceivedByte, Rout) ); // // We need to process out DigiBoard specific 0xFF. // if( ReceivedByte == 0xFF ) { // // We have some special processing to do! // // // Is there a second character available?? // if( Rout == Rin ) { // // The second character isn't available! // AmountInQueue--; DigiDump( DIGIIOCTL, (" NRecvRoutine, 2nd byte not available!\n" ) ); break; } else { // // Get the 2nd characters // SecondReceivedByte = READ_REGISTER_UCHAR( (ControllerBuffer + Rout) ); Rout++; Rout &= Rmax; if( SecondReceivedByte == 0xFF ) { // // We actually received a 0xFF in the data stream. // DigiDump( DIGIIOCTL, (" NRecvRoutine, Actually recv'ed 0xFF\n" ) ); continue; } else { // // This is Line Status information. Is the last // character available?? // if( Rin == Rout ) { // // The 3rd byte isn't available // AmountInQueue--; DigiDump( DIGIIOCTL, (" NRecvRoutine, 3rd byte not available!\n" ) ); break; } Rout++; Rout &= Rmax; } } } } DisableWindow( ControllerExt ); DigiDump( DIGIIOCTL, (" NRecvRoutine, return RecvBytes = %d!\n", AmountInQueue ) ); return( AmountInQueue ); } // end NBytesInRecvBuffer
BOOLEAN PLxEvtInterruptIsr( IN WDFINTERRUPT Interrupt, IN ULONG MessageID ) /*++ Routine Description: Interrupt handler for this driver. Called at DIRQL level when the device or another device sharing the same interrupt line asserts the interrupt. The driver first checks the device to make sure whether this interrupt is generated by its device and if so clear the interrupt register to disable further generation of interrupts and queue a DPC to do other I/O work related to interrupt - such as reading the device memory, starting a DMA transaction, coping it to the request buffer and completing the request, etc. Arguments: Interupt - Handle to WDFINTERRUPT Object for this device. MessageID - MSI message ID (always 0 in this configuration) Return Value: TRUE -- This device generated the interrupt. FALSE -- This device did not generated this interrupt. --*/ { PDEVICE_EXTENSION devExt; BOOLEAN isRecognized = FALSE; union { INT_CSR bits; ULONG ulong; } intCsr; UNREFERENCED_PARAMETER(MessageID); //TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, // "--> PLxInterruptHandler"); devExt = PLxGetDeviceContext(WdfInterruptGetDevice(Interrupt)); // // Read the Interrupt CSR register (INTCSR) // intCsr.ulong = READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr ); // // Is DMA channel 0 (Write-side) Active? // if (intCsr.bits.DmaChan0IntActive) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, " Interrupt for DMA Channel 0 (write)"); devExt->IntCsr.bits.DmaChan0IntActive = TRUE; // // Clear this interrupt. // devExt->Dma0Csr.uchar = READ_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma0_Csr ); devExt->Dma0Csr.bits.Clear = TRUE; WRITE_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma0_Csr, devExt->Dma0Csr.uchar ); isRecognized = TRUE; } // // Is DMA channel 1 (Read-side) Active? // if (intCsr.bits.DmaChan1IntActive) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, " Interrupt for DMA Channel 1 (read)"); devExt->IntCsr.bits.DmaChan1IntActive = TRUE; // // Clear this interrupt. // devExt->Dma1Csr.uchar = READ_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma1_Csr ); devExt->Dma1Csr.bits.Clear = TRUE; WRITE_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma1_Csr, devExt->Dma1Csr.uchar ); isRecognized = TRUE; } if ((isRecognized) && ((devExt->Dma0Csr.bits.Done) || (devExt->Dma1Csr.bits.Done))) { // // A read or a write or both is done. Queue a DPC. // WdfInterruptQueueDpcForIsr( devExt->Interrupt ); } //TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, // "<-- PLxInterruptHandler"); return isRecognized; }
ARC_STATUS HalpEnvironmentCheckChecksum ( VOID ) /*++ Routine Description: This routine checks the NVRAM environment area checksum. N.B. The NVRAM must be mapped before this routine is called. Arguments: None. Return Value: ESUCCESS is returned if the checksum matches. Otherwise, EIO is returned. --*/ { ULONG Checksum1; ULONG Checksum2; PUCHAR Environment; ULONG Index; PNV_CONFIGURATION NvConfiguration; // // Compute the NVRAM environment area checksum. // NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE; Environment = &NvConfiguration->Environment[0]; Checksum1 = 0; for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) { Checksum1 += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]); } // // Merge the checksum bytes from the NVRAM and compare to computed value. // Checksum2 = (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[0]) | (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[1]) << 8 | (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[2]) << 16 | (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[3]) << 24; // // If the checksum mismatches, then return an I/O error. Otherwise, // return a success status. // if (Checksum1 != Checksum2) { return EIO; } else { return ESUCCESS; } }