/**************************************************************************
 *
 * SOURCE FILE NAME = COMPORT.C
 *
 * DESCRIPTIVE NAME =
 *
 * Copyright : COPYRIGHT IBM CORPORATION, 1991, 1992 - PATENT PENDING
 *             LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
 *             REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
 *             RESTRICTED MATERIALS OF IBM
 *             IBM CONFIDENTIAL
 *
 * VERSION =
 *
 * DATE
 *
 * DESCRIPTION
 *
 *
 * FUNCTIONS
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
 * CHANGE ACTIVITY =
 *  DATE      FLAG        APAR   CHANGE DESCRIPTION
 *  --------  ----------  -----  --------------------------------------
 *  mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
 ****************************************************************************/

   /*
   ** include files
   */
#include "types.h"
#include "comport.h"
#include "config.h"


#define BIOS_PORT_DATA_AREA  0x00400000
#define BIOS_INSTALLED_HDWR_AREA 0x00400010

   /*
   ** external global variables
   */
extern CONFIG_INFO Config_info;

   /*
   ** private global variables
   */
static USHORT Com_data[MAX_NUM_IO_ADDRESSES] = {0, 0, 0, 0};


/****************************************************************************
 *
 * FUNCTION NAME = acquire_com_port
 *
 * DESCRIPTION   = This function checks for the availability of an io
 *                 address associated with a com port.  If the address
 *                 is available then the function reserves it.
 *                 The parameter 'io_address' contains the address to
 *                 check and reserve.
 *
 * INPUT         =
 *
 * OUTPUT        = The function returns the value -1 if the address is not
 *                 available. Otherwise, the value 0 is returned.
 *
 * RETURN-NORMAL =
 *
 * RETURN-ERROR  =
 *
 ****************************************************************************/

short acquire_com_port(USHORT io_address)


{
    USHORT *memP, count;
    USHORT far *bios_memP;
    USHORT i;

        /* search local data area  for i/o address
        **  - return failure if the address is taken or the data area is full
        */
    memP = Com_data;
    i = 0;
    while (1)
    {
        if (i >  Config_info.num_of_io_addresses - 1)
            return(-1);
        if (*memP == io_address)
            return(-1);
        if (*memP == 0)
            break;
        memP++;
        i++;
    }

        /* search bios data area  for i/o address
        ** - return failure if the address is taken or if the data area is full
        */
    bios_memP = (USHORT far *) BIOS_PORT_DATA_AREA;
    i = 0;
    while (1)
    {
        if (i > Config_info.num_of_io_addresses - 1)
            return(-1);
        if (*bios_memP == io_address)
            return(-1);
        if (*bios_memP == 0)
            break;
        bios_memP++;
        i++;
    }

        /* address is available - store it
        */
    *memP = io_address;
    *bios_memP = io_address;

        /* increment the number of rs232c adapters
        */
    bios_memP = (USHORT far *)  BIOS_INSTALLED_HDWR_AREA;
    count = (*bios_memP >> 9) & 0x07;
    count++;
    count <<= 9;
    *bios_memP &= 0xf1ff;
    *bios_memP |= count;

        /* return success
        */
    return(0);
}

/****************************************************************************
 *
 * FUNCTION NAME = release_com_port
 *
 * DESCRIPTION   = This function releases the io address associated with
 *                 a com port.
 *                 The parameter 'io_address' is the io address to release.
 *
 * INPUT         = NONE
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/

void release_com_port(USHORT io_address)

{
    USHORT *memP;
    USHORT far *bios_memP;
    USHORT i, count;

        /* search local data area  for i/o address
        **     - return if  the address is not found
        */
    memP = Com_data;
    i = 0;
    while (1)
    {
        if (i > Config_info.num_of_io_addresses - 1)
            return;
        if (*memP == io_address)
        {
            *memP = 0;
            break;
        }
        if (*memP == 0)
            return;
        memP++;
        i++;
    }

        /* move the entries down
        */
    memP = Com_data;
    for (i = 0; i <= Config_info.num_of_io_addresses - 2; i++)
    {
        if (*memP == 0)
        {
            *memP = *(memP + 1);
            *(memP + 1) = 0;
        }
        memP++;
    }

        /* search bios data area for i/o address
        **     -  return if the address is not found
        */
    bios_memP = (USHORT far *) BIOS_PORT_DATA_AREA;
    i = 0;
    while (1)
    {
        if (i > Config_info.num_of_io_addresses - 1)
            return;
        if (*bios_memP == io_address)
        {
            *bios_memP = 0;
            break;
        }
        if (*bios_memP == 0)
            return;
        bios_memP++;
        i++;
    }

        /* move the entries down
        */
    bios_memP = (USHORT far *) BIOS_PORT_DATA_AREA;
    for (i = 0; i <= Config_info.num_of_io_addresses - 2; i++)
    {
        if (*bios_memP == 0)
        {
            *bios_memP = *(bios_memP + 1);
            *(bios_memP + 1) = 0;
        }
        bios_memP++;
    }

        /* decrement the number of rs232c adapters
        */
    bios_memP = (USHORT far *)  BIOS_INSTALLED_HDWR_AREA;
    count = (*bios_memP >> 9) & 0x07;
    count--;
    count <<= 9;
    *bios_memP &= 0xf1ff;
    *bios_memP |= count;

        /* done
        */
    return;
}
