#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;
        }
       Buffer = (PCHAR)Buffer + 1;
    }
    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);
        Buffer = (PCHAR)Buffer + 1;
    }
    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
