567 lines
11 KiB
C
567 lines
11 KiB
C
|
#if defined(JAZZ)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
jxserial.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the serila boot driver for the Jazz system.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Lluis Abello (lluis) 9-Aug-1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode.
|
|||
|
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "fwp.h"
|
|||
|
#include "jazzserp.h"
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialClose (
|
|||
|
IN ULONG FileId
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialMount (
|
|||
|
IN PCHAR MountPath,
|
|||
|
IN MOUNT_OPERATION Operation
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialOpen (
|
|||
|
IN PCHAR OpenPath,
|
|||
|
IN OPEN_MODE OpenMode,
|
|||
|
IN OUT PULONG FileId
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialRead (
|
|||
|
IN ULONG FileId,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Length,
|
|||
|
OUT PULONG Count
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialGetReadStatus (
|
|||
|
IN ULONG FileId
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialSeek (
|
|||
|
IN ULONG FileId,
|
|||
|
IN PLARGE_INTEGER Offset,
|
|||
|
IN SEEK_MODE SeekMode
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialWrite (
|
|||
|
IN ULONG FileId,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Length,
|
|||
|
OUT PULONG Count
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialGetFileInformation (
|
|||
|
IN ULONG FileId,
|
|||
|
OUT PFILE_INFORMATION Finfo
|
|||
|
);
|
|||
|
//
|
|||
|
// Declare and initialize the Serial entry table.
|
|||
|
//
|
|||
|
BL_DEVICE_ENTRY_TABLE SerialEntryTable = {
|
|||
|
SerialClose,
|
|||
|
SerialMount,
|
|||
|
SerialOpen,
|
|||
|
SerialRead,
|
|||
|
SerialGetReadStatus,
|
|||
|
SerialSeek,
|
|||
|
SerialWrite,
|
|||
|
SerialGetFileInformation,
|
|||
|
(PARC_SET_FILE_INFO_ROUTINE)NULL
|
|||
|
};
|
|||
|
|
|||
|
PCHAR PathNameSerialPort0 = "multi(0)serial(0)";
|
|||
|
PCHAR PathNameSerialPort1 = "multi(0)serial(1)";
|
|||
|
|
|||
|
#define SP_BASE(Fid) PSP_WRITE_REGISTERS SP; \
|
|||
|
SP = (PSP_WRITE_REGISTERS)BlFileTable[Fid].u.SerialContext.PortBase
|
|||
|
//
|
|||
|
// Define function prototypes
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
SerialBootSetup(
|
|||
|
IN ULONG FileId
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialGetFileInformation (
|
|||
|
IN ULONG FileId,
|
|||
|
OUT PFILE_INFORMATION Finfo
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function returns EINVAL as no FileInformation can be
|
|||
|
returned for the Serial line driver.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
The arguments are not used.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
EINVAL is returned
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return EINVAL;
|
|||
|
}
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialClose (
|
|||
|
IN ULONG FileId
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function closes the file table entry specified by the file id.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileId - Supplies the file table index.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ESUCCESS is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BlFileTable[FileId].Flags.Open = 0;
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialBootWrite(
|
|||
|
CHAR Char,
|
|||
|
ULONG SP
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine writes a character to the serial port.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Char - Character to write.
|
|||
|
|
|||
|
SP - Base address of the serial port.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the operation is performed without errors, ESUCCESS is returned,
|
|||
|
otherwise an error code is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
UCHAR DataByte;
|
|||
|
|
|||
|
//
|
|||
|
// wait for transmitter holding register to be empty
|
|||
|
//
|
|||
|
do {
|
|||
|
DataByte=READ_REGISTER_UCHAR(&((PSP_READ_REGISTERS)SP)->LineStatus);
|
|||
|
} while (((PSP_LINE_STATUS)(&DataByte))->TransmitHoldingEmpty == 0);
|
|||
|
|
|||
|
//
|
|||
|
// transmit character
|
|||
|
//
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP)->TransmitBuffer,Char);
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
ARC_STATUS
|
|||
|
SerialWrite (
|
|||
|
IN ULONG FileId,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Length,
|
|||
|
OUT PULONG Count
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the write operation for the ARC firmware
|
|||
|
serial port driver.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileId - Supplies a file id.
|
|||
|
|
|||
|
Buffer - Supplies a pointer to a buffer containing the characters to
|
|||
|
write to the serial port.
|
|||
|
|
|||
|
Length - Supplies the length of Buffer.
|
|||
|
|
|||
|
Count - Returns the count of the characters that were written.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the operation is performed without errors, ESUCCESS is returned,
|
|||
|
otherwise an error code is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ARC_STATUS Status;
|
|||
|
|
|||
|
for (*Count=0; *Count < Length; (*Count)++) {
|
|||
|
if (Status=SerialBootWrite(*(PCHAR)Buffer,
|
|||
|
BlFileTable[FileId].u.SerialContext.PortBase)
|
|||
|
) {
|
|||
|
return Status;
|
|||
|
}
|
|||
|
((PCHAR)Buffer)++;
|
|||
|
}
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialRead (
|
|||
|
IN ULONG FileId,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Length,
|
|||
|
OUT PULONG Count
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the read operation for the ARC firmware
|
|||
|
serial port driver.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileId - Supplies a file id.
|
|||
|
|
|||
|
Buffer - Supplies a pointer to a buffer where the characters read
|
|||
|
from the serial port will be stored.
|
|||
|
|
|||
|
Length - Supplies the length of Buffer.
|
|||
|
|
|||
|
Count - Returns the count of the characters that were read.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the operation is performed without errors, ESUCCESS is returned,
|
|||
|
otherwise an error code is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
UCHAR DataByte;
|
|||
|
SP_BASE(FileId);
|
|||
|
for (*Count=0; *Count < Length; (*Count)++) {
|
|||
|
//
|
|||
|
// if no characters are available, then set data terminal ready
|
|||
|
// and continue polling.
|
|||
|
//
|
|||
|
DataByte = READ_REGISTER_UCHAR(&((PSP_READ_REGISTERS)SP)->LineStatus);
|
|||
|
if ((((PSP_LINE_STATUS)(&DataByte))->DataReady == 0)) {
|
|||
|
DataByte=0;
|
|||
|
((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady=1;
|
|||
|
((PSP_MODEM_CONTROL)(&DataByte))->Interrupt=1;
|
|||
|
WRITE_REGISTER_UCHAR(&SP->ModemControl,DataByte);
|
|||
|
}
|
|||
|
//
|
|||
|
// Poll until a character is available from the serial port
|
|||
|
//
|
|||
|
do {
|
|||
|
DataByte=READ_REGISTER_UCHAR(&((PSP_READ_REGISTERS)SP)->LineStatus);
|
|||
|
} while ((((PSP_LINE_STATUS)(&DataByte))->DataReady == 0));
|
|||
|
|
|||
|
//
|
|||
|
// turn off data terminal ready
|
|||
|
//
|
|||
|
DataByte=0;
|
|||
|
((PSP_MODEM_CONTROL)(&DataByte))->Interrupt=1;
|
|||
|
WRITE_REGISTER_UCHAR(&SP->ModemControl,DataByte);
|
|||
|
|
|||
|
//
|
|||
|
// Read character
|
|||
|
//
|
|||
|
*(PCHAR)Buffer = READ_REGISTER_UCHAR(&((PSP_READ_REGISTERS)SP)->ReceiveBuffer);
|
|||
|
((PCHAR)Buffer)++;
|
|||
|
}
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialOpen (
|
|||
|
IN PCHAR OpenPath,
|
|||
|
IN OPEN_MODE OpenMode,
|
|||
|
IN OUT PULONG FileId
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine opens the specified serial port.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
OpenPath - Supplies the pathname of the device to open.
|
|||
|
|
|||
|
OpenMode - Supplies the mode (read only, write only, or read write).
|
|||
|
|
|||
|
FileId - Supplies a free file identifier to use. If the device is already
|
|||
|
open this parameter can be used to return the file identifier
|
|||
|
already in use.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the open was successful, ESUCCESS is returned, otherwise an error code
|
|||
|
is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG Port;
|
|||
|
//
|
|||
|
// Check for the serial port to open 0,1
|
|||
|
//
|
|||
|
if (FwGetPathMnemonicKey(OpenPath,
|
|||
|
"serial",
|
|||
|
&Port
|
|||
|
)) {
|
|||
|
return ENODEV;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Init file table
|
|||
|
//
|
|||
|
BlFileTable[*FileId].u.SerialContext.PortNumber = Port;
|
|||
|
BlFileTable[*FileId].u.SerialContext.PortBase = COMPORT1_VIRTUAL_BASE+0x1000*Port;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the serial port.
|
|||
|
//
|
|||
|
SerialBootSetup(BlFileTable[*FileId].u.SerialContext.PortBase);
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
SerialBootSetup(
|
|||
|
IN ULONG SP
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine initializes the serial port controller.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SP - Supplies the virtual address of the serial port.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
UCHAR Trash;
|
|||
|
UCHAR DataByte;
|
|||
|
//
|
|||
|
// Clear the divisor latch, clear all interrupt enables, and reset and
|
|||
|
// disable the FIFO's.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP)->LineControl, 0x0);
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP)->InterruptEnable, 0x0);
|
|||
|
DataByte = 0;
|
|||
|
((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
|
|||
|
((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP)->FifoControl, DataByte);
|
|||
|
|
|||
|
//
|
|||
|
// Set the divisor latch and set the baud rate to 9600 baud.
|
|||
|
//
|
|||
|
|
|||
|
DataByte = 0;
|
|||
|
((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP)->LineControl, DataByte);
|
|||
|
if (MctadrRev2) {
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP)->TransmitBuffer, 52);
|
|||
|
} else {
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP)->TransmitBuffer, BAUD_RATE_9600);
|
|||
|
}
|
|||
|
// WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP)->TransmitBuffer, BAUD_RATE_19200);
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP)->InterruptEnable, 0x0);
|
|||
|
|
|||
|
//
|
|||
|
// Clear the divisor latch and set the character size to eight bits
|
|||
|
// with one stop bit and no parity checking.
|
|||
|
//
|
|||
|
|
|||
|
DataByte = 0;
|
|||
|
((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP)->LineControl, DataByte);
|
|||
|
|
|||
|
//
|
|||
|
// Set data terminal ready and request to send.
|
|||
|
// And open interrupt tristate line
|
|||
|
//
|
|||
|
|
|||
|
DataByte = 0;
|
|||
|
((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
|
|||
|
((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
|
|||
|
((PSP_MODEM_CONTROL)(&DataByte))->Interrupt=1;
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP)->ModemControl, DataByte);
|
|||
|
|
|||
|
Trash = READ_REGISTER_UCHAR(&((PSP_READ_REGISTERS)SP)->LineStatus);
|
|||
|
Trash = READ_REGISTER_UCHAR(&((PSP_READ_REGISTERS)SP)->ReceiveBuffer);
|
|||
|
}
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialGetReadStatus (
|
|||
|
IN ULONG FileId
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine checks to see if a character is available from the serial line.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileId - Supplies a file identifier.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns ESUCCESS is a byte is available, otherwise EAGAIN is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
UCHAR DataByte;
|
|||
|
SP_BASE(FileId);
|
|||
|
DataByte = READ_REGISTER_UCHAR(&((PSP_READ_REGISTERS)SP)->LineStatus);
|
|||
|
if ((((PSP_LINE_STATUS)(&DataByte))->DataReady == 0)) {
|
|||
|
return EAGAIN;
|
|||
|
}
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialMount (
|
|||
|
IN PCHAR MountPath,
|
|||
|
IN MOUNT_OPERATION Operation
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return EINVAL;
|
|||
|
}
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialSeek (
|
|||
|
IN ULONG FileId,
|
|||
|
IN IN PLARGE_INTEGER Offset,
|
|||
|
IN SEEK_MODE SeekMode
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ESUCCESS is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
SerialInitialize(
|
|||
|
IN OUT PDRIVER_LOOKUP_ENTRY LookupTableEntry,
|
|||
|
IN ULONG Entries
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine initializes the serial device dispatch table
|
|||
|
and the entries in the driver lookup table.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LookupTableEntry - Supplies a pointer to the first free location in the
|
|||
|
driver lookup table.
|
|||
|
|
|||
|
Entries - Supplies the number of free entries in the driver lookup table.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the driver lookup table, and increment the pointer.
|
|||
|
//
|
|||
|
|
|||
|
LookupTableEntry->DevicePath = PathNameSerialPort0;
|
|||
|
LookupTableEntry->DispatchTable = &SerialEntryTable;
|
|||
|
|
|||
|
if (Entries>1) {
|
|||
|
LookupTableEntry++;
|
|||
|
LookupTableEntry->DevicePath = PathNameSerialPort1;
|
|||
|
LookupTableEntry->DispatchTable = &SerialEntryTable;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif
|